Chrome.runtime.onMessage asynchronous wait response

I want to use async wait in the onMessage listener:

chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) =>{ var key = await getKey(); sendResponse(key); }); 

However, I get undefined when I post a message.

From the documentation for chrome.runtime.onMessage.addListener:

This function becomes invalid when the event receiver returns, unless you return true from the event listener to indicate that you want to send the response asynchronously (this will cause the message channel to open to the other end before sending sendResponse).

This works when I use callback.

 chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) =>{ getKey(key => { sendResponse(key); }); return true; }); 

However, I would like to use the wait syntax. But it does not work and still returns undefined:

 chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) =>{ var key = await getKey(); sendResponse(key); return true; }); 
+13
source share
3 answers

I get around by extracting into an asynchronous function.

 chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { doSomethingWith(request).then(sendResponse); return true; // return true to indicate you wish to send a response asynchronously }); async function doSomethingWith(request) { var key = await getKey(); // await ..... return key; } 

The return value of the async function is implicitly Promise.resolve in Promise.resolve . See asynchronous dock .

Look at the message .

+8
source

I'm not sure if the Chrome extension runtime supports async / await syntax, but you can use a transporter (like Babel) to convert it, for example, to ES5. You can then define the wrapper function as follows:

 function asChromeListener(listener) { return (message, sender, sendResponse) => { const returnValue = listener(message, sender); if (isPromise(returnValue)) { returnValue.then(sendResponse); return true; } else { if (typeof returnValue !== 'undefined') { sendResponse(returnValue); } return false; } }; } function isPromise(value) { return typeof value === 'object' && value !== null && 'then' in value && 'catch' in value; } 

What you can use as:

 chrome.runtime.onMessage.addListener(asChromeListener(async (message, sender) => { return await doMyAsyncWork(message); }); 

Since we use TypeScript , here is also a snippet that we actually use (with generic types).

 export function asChromeListener<M, S, R extends Function>(listener: (message: M, sender: S) => any) { return (message: M, sender: S, sendResponse: R) => { const returnValue = listener(message, sender); if (isPromise(returnValue)) { returnValue.then(sendResponse); return true; } else { if (typeof returnValue !== 'undefined') { sendResponse(returnValue); } return false; } }; } function isPromise(value: any) { return typeof value === 'object' && value !== null && 'then' in value && 'catch' in value; } 
+2
source

Honestly, it seems that Google Chrome extensions do not support the await keyword. I have successfully used the asynchronous chrome.runtime.onMessage.addListener before, and every time I try to use await , I see this syntax error in Chrome debugging tools, in the line that I use await :

wait is not supported

Here is how I tested:

I created a very simple listener:

 chrome.runtime.onMessage.addListener(function(data, MessageSender, sendResponse) { sendResponse(awaitTester); var async = true; // returns true if asyncronous is needed if (async) return true; }); 

My awaitTester function looks like this:

 function awaitTester() { var prom = new Promise(function(resolve, reject) { setTimeout(function() { resolve('test'); }, 4000); }); var awaited = await prom; return awaited; } 

finally, my message sender is what you expect:

 chrome.runtime.sendMessage({}, function(message) { debugger; console.log(message); }); 

And in the debugger / console, I always get undefined .

+1
source

All Articles