首页 > 解决方案 > 响应未定义为 async、await、promise

问题描述

在我的eventPage.js(背景,持久=假):

chrome.runtime.onMessage.addListener(async function(request, sender, sendResponse) {

    await new Promise((resolve, reject) => { 
        chrome.downloads.search({id: files[i]}, function (item) { 
            sendfiles.push(item[0].id);
            resolve();
        });
    });

    console.log(sendfiles); // contains (item[0].id), means it did wait.

    sendResponse("hello"); // Should send hello back

    return true;
});

在我的popup.js

chrome.runtime.sendMessage("",(response) => {
    alert(response); // alerts undefinded instead of hello
});

我的错误: Unchecked runtime.lastError: The message port closed before a response was received.

正如代码注释中所写,它应该响应来自popup.jswith的请求"hello",但因为它在 中等待,所以Promise我得到了错误并且在我可以之前response变成了(我猜这就是发生的事情)..undefindedsendResponse"hello"

标签: javascriptgoogle-chrome-extensionpromiseasync-await

解决方案


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

这里

但是使用 async-await,你的函数会返回一个 Promise。

所以你想这样做:

chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {

    chrome.downloads.search({id: files[i]}, 
      function (item) { 
        sendResponse(item[0].id);
      }
    );

   return true;
});

但实际上,你想这样做:

chrome.runtime.onMessage.addListener(
  (req, sender, sendResponse) => {
    chrome.downloads.search({id: files[i]}, 
       item => sendResponse(item[0].id);
    );
   return true;
});

或者至少,我愿意!:-)

对于循环。你想返回一个文件数组。所以你在你的程序中做的是:

  1. 创建一个“文件的承诺或未定义”的数组
  2. 等待所有这些 Promise 解决。
  3. 过滤掉未定义的。
  4. 返回文件数组。
chrome.runtime.onMessage.addListener(
  (req, sender, sendResponse) => {
   if (req !== "files") { return } // why wait?

   Promise.all(files.map(file => 
     new Promise(resolve =>     
       chrome.downloads.search({id: file},
         item => resolve(item[0].exists ? 
         {
            filename: [item[0].filename, 
            id: item[0].id]
          } : undefined)))))
    .then(res => res.filter(i => !!i)) //remove empty
    .then(sendResponse)

  return true;
});

基本上,如果您使用循环或变量,那么您做错了。仅限常量和函数。

希望这可以帮助。


推荐阅读