skip to Main Content

Can someone help me understand the difference between the two blocks of code below? When I call await in the listener, the caller receives undefined.

chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
    // (async () => {
        const response = await executeScript(request);
        if (response) {
            console.log('Content script received message:', response);
            sendResponse(response[0].result);
        }
    // })();
    return true;
});

However, when I use the immediately-invoked async function expression, the returned value is what is returned by executeScript.

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    (async () => {
        const response = await executeScript(request);
        if (response) {
            console.log('Content script received message:', response);
            sendResponse(response[0].result);
        }
    })();
    return true;
});

When I call await executeScript, I am assuming that it stops the execution of the async function and suspends it until the awaited promise is resolved or rejected. How is this different from the immediately-invoked async function expression?

2

Answers


  1. Your first code block is passing an async function to code that doesn’t expect to receive one. Specifically, the onMessage code expects a function that returns either a boolean or undefined, but you’re passing it a function that returns a promise (because all async functions return promises). Since it’s not documented to handle that, that’s probably wrong. It won’t wait for the promise to settle, apparently (from your question) won’t do the right thing when it sees a value it didn’t expect, and won’t handle promise rejections.

    Your second code block is returning what the onMessage event code expects to see (true, in your case), so that’s more likely to be right (in that regard).

    There’s a separate problem with the second code block though: Nothing handles promise rejection, so if an error occurs in the function, you’ll get an "unhandled rejection" warning in the console. (In some environments, it could be more significant than just a warning.) If you’re going to run an async function and not pass its promise on to anything, you need to be sure the function can’t throw an error and reject its promise — for instance, by wrapping everything in trycatch:

    chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
        (async () => {
            try {
                const response = await executeScript(request);
                if (response) {
                    console.log("Content script received message:", response);
                    sendResponse(response[0].result);
                }
            } catch (error) {
                // Handle/report the error...
            }
        })();
        return true;
    });
    

    (Or by using .then/.catch instead of an async IIFE, but it’s nearly as verbose.)

    Login or Signup to reply.
  2. In the First Block of code, you have a created a async callback that runs as a promise and goes under pending state such that no value is returned until that promise is resolved.

    In the Second Block of Code, the callback function is synchronous which initiates a async nameless-function that runs separately (independently from callback function) and returns true without waiting for the promise to be completed, sendResponse will be called as implemented in block.

    To be more Precise,

    Block 1 Steps:

    1. Initiates a async Callback
    2. Move over the next step (whatever is after addListener)

    Block 2 Steps:

    1. Initiates a callback and
      i. Initiates a async Callback
      ii. returns true
    2. waits for it to complete
    3. Move over the next step (whatever is after addListener)
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search