The message port closed before a response was received

Started by axel.hennig, March 30, 2022, 10:46:45 PM

Previous topic - Next topic

axel.hennig

Hello,

I'm currently trying to develop an app and one async sub-function takes a lot of time. When running this within IMatch the app stops "half-the-way" and the app reloads. When running in Chrome it goes through, but on the console I get the message {"message":"The message port closed before a response was received."}.

Google-ing this problems some answers (Stackoverflow) say:

  • must have something to do with Chrome-extensions
  • is related to the "background message listener" => don't know what this is and I think I'm not (actively) using it

Does someone know this problem and how to fix it?

Mario

What are you're trying to do?
This looks pretty much like a timeout...
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

axel.hennig

Hi Mario,

I'm with you that this looks like a "timeout-problem". But how do I tell IMatch-chromium or Chrome: "Keep the port open, the app is still running, everything fine"?

To answer your question what I'm trying to do:
(1) I'm looping over different category-ids and request the file-ids within every category (v1/categories endpoint)
(2) For all the file-ids within one category I request several fields ('id,ext,name,class') plus four 'var**' objects (v1/files endpoint)
(3) With the result of step (2) a textfile is written

When I do not request the four 'var**' objects Chrome does not put the "port closed" message. That's also an indication for "timeout".

I've also used 'page' and 'pagesize' within the 'v1/files' endpoint, but didn't help...

The (simplified) code is below:

async function mySubFunction (allCategoryIds) {

    for (const oneCategoryId of allCategoryIds) {
   
        await IMWS.get('v1/categories',{
        id: oneCategoryId,
        fields: 'files',
        }).then(async response => {

            let fileIdsString = response.categories[0].files.toString();
           
            await IMWS.post('v1/idlist',{
                name: 'fileIdsIdlist',
                op: 'set',
                id: fileIdsString,
            });
           
            if (fileIdsString != '') {

                let outputForTextFile = '';

                let result = await IMWS.get('v1/files',{
                    idlist: 'fileIdsIdlist',
                    escapevariables: false,
                    fields: 'id,ext,name,class',
                    var**: // four different 'var**'
                });
               
                for (let i = 0; i < result.files.length; i++) {
                    // do some stuff with the 'result' variable ans store it in 'outputForTextFile'
                };
               
                IMatch.writeTextFile({
                    // generate a text-file with what is stored in 'outputForTextFile'
                });
               
            };
           
            await IMWS.delete('v1/idlist',{
                name: 'fileIdsIdlist',
            });
           
        });

    };
   
};

Mario

Don't mix await with then() - first statement.
await returns a promise, which is, at some unknown later time, fulfilled. So:

let categoryData = await  IMWS.get('v1/categories',{...
let fileIdsString = response.categories[0].files.toString();
let workDone = await IMWS.post('v1/idlist',{
...

Set some breakpoints in your code (in the F12 developer console in your browser) and see how your loop actually works.
Or just add some console.log('text') calls so you can see what your loop does.

You don't really await your calls, you mix await with then, you're even writing text files and all that in a tight loop.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

axel.hennig

Hi Mario,

thanks for your answer.

I've changed the code to what you said, but the problem still exists. I made a minimum-working-example (see code below) and also here the problem ("port closed before a response...") occurs, but just "sometimes".

Any other idea what the problem could be?


async function mySubFunction (allCategoryIds) {
   
    for (const id of allCategoryIds) {
       
        let resultCat = await IMWS.get('v1/categories',{
        id: id,
        fields: 'files'
        });
       
        let fileIdsString = resultCat.categories[0].files.toString();
       
        let resultPostIdlist = await IMWS.post('v1/idlist',{
            name: 'fileIdsIdlist',
            op: 'set',
            id: fileIdsString
        });
       
    }
   
}


Still google-ing, but don't know how to include this in my code...

If a browser.runtime.onMessage callback does not return a Promise, browser.runtime.sendMessage will be rejected with the following error, causing noise in the console: "The message port closed before a response was received."

Mario

I have tried your code both in Chrome and in an IMatch App panel.
I fed a list of all category ids in the database (1700 categories in total).
Added some console logs to see what's happening.
Works OK.

async function mySubFunction (allCategoryIds) {

    let processed = 0;

    for (const id of allCategoryIds) {
       
        console.log(`${id}`);

        let resultCat = await IMWS.get('v1/categories',{
            id: id,
            fields: 'files'
        });
       
        let fileIdsString = resultCat.categories[0].files.toString();
       
        let resultPostIdlist = await IMWS.post('v1/idlist',{
            name: 'fileIdsIdlist',
            op: 'set',
            id: fileIdsString
        });
        console.log(`${id} done.`);
        processed++;
    }

    console.log(`${processed} categories to processed.`);
}
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

axel.hennig

Ok, thanks for testing. Then, the problem should be on my end... let's see if I can figure it out.

Mario

The latest example does basically only fetches the files in a category and stores them into an idlist.
The next iteration does the same, overwriting the idlist.
If your real loop contains any "then" and await - don't mix!
Don't write to text files in a loop, prepare the data and then write outside the loop. Writing to files is slow and may block for along time.
Use console.log to see if your code does what you think it does, and in the correct order.
Remove some async calls (e.g. comment out everything except the IMWS.get('v1/categories') and see if the problem goes away. If so, uncomment the next segment, rinse and repeat.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

axel.hennig

The last example I've posted is just a minimum-working-example where I got "sometimes" this message.

My real code currently is not mixing "await" and "then". It uses only "await".

I have to write the text files in a loop (at least I think so), because I need one textfile per category. In your example with the 1700 categories I would need 1700 textfiles.

I've used console.log to see what the code is doing and it is doing what I want it to do. The code is running until the end (just putting this "The message port closed before a response was received" message in the console) and the output is exactly what I want to have. Right now the code was also successful in an IMatch app panel (not sure why it failed couple of test before).

I will try to come up with another working-example where the message shows up really every time (at least on my end). Or I just live with the current situation since it seems to work (have to further test)...

Mario

-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook