【问题标题】:Response is undefinded with async, await, promise [duplicate]使用 async、await、promise 未定义响应 [重复]
【发布时间】:2020-06-06 18:34:27
【问题描述】:

在我的eventPage.js(background, persistent=false):

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.

正如代码的cmets中所写,它应该用"hello"响应来自popup.js的请求,但是因为它在Promise中等待,所以我收到错误并且response变成@987654331 @ 之前我可以sendResponse 我的"hello" (我猜这就是发生的事情)..

【问题讨论】:

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


【解决方案1】:

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

来自here

但是使用 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. 创建一个“A Promise of a file or undefined”数组
  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;
});

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

希望这会有所帮助。

【讨论】:

  • 看起来差不多。
  • 感谢指正!虽然在我的代码中,我在 for 循环中有 chrome.downloads.search。在每个循环中,在 downloads.search 中,它会将一个项目添加到稍后将作为响应发送的数组中。我该怎么做?此外,一些奇怪的事情正在发生,因为它正在执行chrome.downloads.search 并行。代码:pastebin.com/0zmV76fi
  • 为你更新了。
猜你喜欢
  • 2017-10-26
  • 2021-10-05
  • 2021-02-17
  • 2019-05-24
  • 2021-11-05
  • 1970-01-01
  • 2017-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多