chrome.runtime.onMessage response with async await

心不动则不痛 提交于 2020-04-07 18:44:28

问题


I want to use async await in an onMessage listener:

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

However I get undefined when I send a message.

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

This function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).

This works when I use a callback.

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

However I would like to leverage the await syntax. But it does not seem to work and still returns undefined:

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

回答1:


I do work-around by extracting to an async function.

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  doSomethingWith(request).then(sendResponse);
  return true; // return true to indicate you want to send a response asynchronously
});

async function doSomethingWith(request) {
  var key = await getKey();
  // await .....
  return key;
}

The return value of an async function is implicitly wrapped in Promise.resolve. See async doc.

See onMessage.




回答2:


Not sure if Chrome extension runtime environment supports the async/await syntax, but you can use a transpiler (i.e. Babel) to have it converted to for example ES5. Then you can define a wrapper function like this:

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;
}

Which you can then use like:

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

Since we use TypeScript, here's also the 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;
}



回答3:


Honestly, it looks like Google Chrome Extensions don't support the await keyword. I've successfully used asynchronous chrome.runtime.onMessage.addListener's before, and every time I try to use await I see this syntax error in the Chrome Debugging Tools, on the line that I use await:

Here's how I've been testing:

I created a very basic 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'd expect:

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

And in the debugger / console I always get undefined.



来源:https://stackoverflow.com/questions/44056271/chrome-runtime-onmessage-response-with-async-await

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!