Home  >  Article  >  Web Front-end  >  Why Doesn\'t `sendResponse()` Wait for Asynchronous Functions in Chrome\'s `onMessage` Listener?

Why Doesn\'t `sendResponse()` Wait for Asynchronous Functions in Chrome\'s `onMessage` Listener?

DDD
DDDOriginal
2024-11-22 16:29:14692browse

Why Doesn't `sendResponse()` Wait for Asynchronous Functions in Chrome's `onMessage` Listener?

"sendResponse" Not Waiting for Asynchronous Function or Promise's Resolve

Introduction

When sending a message from popup.js to contentscript.js, the sendResponse() function is expected to wait for the getThumbnails() function to complete. However, in this scenario, sendResponse() is not waiting, causing issues with Asynchronicity.

Issue Explanation

The main issue is that Chrome still lacks support for promises in the returned value of onMessage listeners in both Manifest V2 and V3. As a result, when your listener declares the async keyword, it returns a promise instead of the literal true value required by onMessage. This causes the returned promise to be ignored, closing the messaging channel prematurely.

Solution: Making the Listener Compatible

To ensure compatibility with the current Chrome implementation, you can remove the async keyword from before the function parameters (request, sender, sendResponse) and declare a separate asynchronous function to handle the message processing:

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  if (msg.message === "get_thumbnails") {
    processMessage(msg).then(sendResponse);
    return true; // keep the messaging channel open for sendResponse
  }
});

async function processMessage(msg) {
  console.log('Processing message', msg);
  // ... asynchronous processing code
  return 'foo';
}

Patching the API for Allow Async/Promise Listener

Alternatively, you can patch the API to allow asynchronous/promise listeners by adding the following code to each script using chrome.runtime.onMessage:

if ('crbug.com/1185241') { // replace with a check for Chrome version that fixes the bug
  const {onMessage} = chrome.runtime, {addListener} = onMessage; 
  onMessage.addListener = fn => addListener.call(onMessage, (msg, sender, respond) => {
    const res = fn(msg, sender, respond);
    if (res instanceof Promise) return !!res.then(respond, console.error);
    if (res !== undefined) respond(res);
  });
}

With the patch applied, you can return the value directly:

chrome.runtime.onMessage.addListener(async msg => {
  if (msg === 'foo') {
    const res = await fetch('https://foo/bar');
    const payload = await res.text();
    return {payload};
  }
});

The above is the detailed content of Why Doesn\'t `sendResponse()` Wait for Asynchronous Functions in Chrome\'s `onMessage` Listener?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn