【问题标题】:chrome.runtime.onMessage response with async await带有异步等待的 chrome.runtime.onMessage 响应
【发布时间】:2017-10-18 18:29:50
【问题描述】:

我想在 onMessage 监听器中使用异步等待:

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

但是当我发送消息时我得到了不确定。

来自 chrome.runtime.onMessage.addListener 的文档:

当事件监听器返回时,该函数失效,除非 您从事件侦听器返回 true 表示您希望发送一个 异步响应(这将保持消息通道对 另一端直到调用 sendResponse)。

这在我使用回调时有效。

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

但是我想利用 await 语法。但它似乎不起作用,仍然返回 undefined:

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

【问题讨论】:

    标签: javascript google-chrome-extension async-await


    【解决方案1】:

    我通过提取到异步函数来解决问题。

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

    async 函数的返回值隐含在 Promise.resolve 中。见async doc

    onMessage

    【讨论】:

    • 谢谢!在我从侦听器中删除异步并按照您的说明操作后效果很好
    【解决方案2】:

    不确定 Chrome 扩展运行时环境是否支持 async/await 语法,但您可以使用转译器(即 Babel)将其转换为例如 ES5。然后你可以像这样定义一个包装函数:

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

    然后你可以像这样使用:

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

    由于我们使用 TypeScript,这也是我们实际使用的 sn-p(使用泛型类型)。

    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】:

      老实说,Google Chrome 扩展程序似乎不支持 await 关键字。我之前已经成功使用过异步chrome.runtime.onMessage.addListener,每次尝试使用await时,我都会在Chrome调试工具中看到这个语法错误,就在我使用await的那一行:

      这是我的测试方式:

      我创建了一个非常基本的监听器:

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

      我的awaitTester 函数如下所示:

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

      最后,我的消息发送者是你所期望的:

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

      在调试器/控制台中,我总是得到undefined

      【讨论】:

      • 您没有对 async/await 的原生支持 - 您需要使用某种 tranapiller 来实现该功能。
      【解决方案4】:

      有响应时调用的函数(最多一次)。参数应该是任何 JSON-ifiable 对象。如果您在同一个文档中有多个 onMessage 侦听器,那么只有一个可以发送响应。当事件侦听器返回时,此函数无效,除非您从事件侦听器 return true 表明您希望异步发送响应(这将保持消息通道对另一端开放,直到调用 sendResponse )。

      https://developer.chrome.com/docs/extensions/reference/runtime/#event-onMessage

      不得不说官方文档真的很难读。

      【讨论】:

        【解决方案5】:

        你可以试试这个

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

        【讨论】:

          猜你喜欢
          • 2011-09-03
          • 2020-06-09
          • 2020-12-03
          • 1970-01-01
          • 2020-12-09
          • 1970-01-01
          • 2013-08-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多