Extension sendMessage API documentation for asynchronous responses should be clearer |
||||
Issue descriptionChrome Version : 67.0.3396.99 OS Version: 10.0 Using the chrome API chrome.runtime.onMessage.addListener to respond to a message chrome.runtime.sendMessage while executing the sendResponse method inside a promise or callback will cause a disconnect. URLs (if applicable) : Other browsers tested: Chrome API. What steps will reproduce the problem? 1. Setup a chrome.runtime.onMessage.addListener in a background script with a response sent in a callback/promise. 2. Setup a message sender chrome.runtime.sendMessage from a content script with the 'response' method to console.log the response value. 3. Send a message from the content script and then run chrome.runtime.lasterror What is the expected result? The content script stays connected to the backend messaging script until the message is received or the sendResponse message terminates. What happens instead of that? Content script receives a disconnected message. "The message port closed before a response was received." Please provide any additional information below. Attach a screenshot if possible. UserAgentString: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
,
Jul 3
Background Code:
class Message {
/**
* Stores a message to the chrome synced storage.
* @param {{id: string, msg: string}} msg is the message object to be stored.
*/
static store (msg) {
//...
}
/**
* Retrieves a message from synced storage.
* @param {string} msg is the case id.
*/
static retrieve (msg) {
return new Promise((resolve) => {
chrome.storage.sync.get(msg, rec => {
resolve(rec[msg]);
});
});
}
}
/** Creates a runtime listener for requests. */
chrome.runtime.onMessage.addListener(
(request, sender, sendResponse) => {
if(request.messageStore) {
Message.store(request.messageStore);
}
if(request.messageRetrieve) {
Message.retrieve(request.messageRetrieve).then(rec => {
sendResponse({msg: rec});
return true;
});
}
});
Content Script:
chrome.runtime.sendMessage({messageRetrieve:this.caseid}, msg => {
console.log(chrome.runtime.lastError);
console.log(msg);
});
,
Jul 3
I figured it out, I needed to move the 'return true' outside the asynchronous method.
,
Jul 3
,
Jul 3
Yes, you need "return true" as per the documentation: https://developer.chrome.com/extensions/runtime#event-onMessage
,
Jul 3
BTW, this problem is brought up regularly on stackoverflow.com so apparently the documentation needs an update. I'd say the messaging article should have a more prominent async case description and a demo code: https://developer.chrome.com/extensions/messaging
,
Jul 3
rlyons@google.com - Thanks for filing the issue...!! Could you please provide a sample test file/url to test the issue from TE-end as the code at comment #3 is not of much help to us. This will help us in triaging the issue further. The code at comment #3 is not of much help. Thanks...!!
,
Jul 3
@6 I agree - this has definitely come up a lot. We already document it in the messaging article [1], but it's not visible enough. Maybe the demo code like you suggest, and perhaps also alluding to it in the runtime.sendMessage documentation - I'll see if we can add those soon. Updating the bug description and components. [1] We say: In the above example, sendResponse was called synchronously. If you want to asynchronously use sendResponse, add return true; to the onMessage event handler. ... Note: The sendResponse callback is only valid if used synchronously, or if the event handler returns true to indicate that it will respond asynchronously. The sendMessage function's callback will be invoked automatically if no handlers return true or if the sendResponse callback is garbage-collected. |
||||
►
Sign in to add a comment |
||||
Comment 1 by lucmult@chromium.org
, Jul 3Components: Platform>Extensions>API