【问题标题】:How do I make use of await and async in this function?如何在此函数中使用 await 和 async?
【发布时间】:2021-08-02 22:21:31
【问题描述】:

我正在开发一个即将完成的 Chrome 扩展程序。目前,当数据被提取完成时,我从我的 fetch 中得到响应,而不是正确的顺序。我想我将不得不使用 await 和 async 但我不确定如何。值得注意的是,我在后台脚本和使用 sendMessage 的内容脚本之间建立了“连接”。

我确实尝试过按照本教程进行操作,如果您以前做过,可能非常容易理解,但我不明白我的价格该怎么做 => {} 教程:https://web.archive.org/web/20201227111539/https://dev.to/shoupn/javascript-fetch-api-and-using-asyncawait-47mp

内容.js

function getPrices() {
    for (var i = 0; i < 35; i++) {
        chrome.runtime.sendMessage(
            {contentScriptQuery: "queryPrice", itemURL: skins[priceNumber]},
            price => {
                console.log(price);
            });

        priceNumber = priceNumber + 1;
    }
...
}

background.js

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {
      if (request.contentScriptQuery == "queryPrice") {
        var url = "https://pixelboii.wtf/steamvalue.json";
        var skinFullName = request.itemURL;
        fetch(url)
            .then(res => res.json())
            .then(price => {
              sendResponse(price.items_list[skinFullName].price["7_days"].average);
            })
            .catch(err => { throw err });
        return true;  // Will respond asynchronously.
      }
    });

感谢所有回复!

【问题讨论】:

  • 您显示的代码建议您发送一次消息...那么响应的顺序怎么可能是错误的呢?
  • 如果你在某种循环中调用 sendMassage - 展示你是如何做的 - 因为第一个代码不会从 async/await 中受益,因为该代码中没有承诺
  • 哦,绝对的,更新了帖子!
  • 你能解释一下正确顺序是什么意思吗?
  • 正确顺序:要获取的第一个项目也应该是返回的第一个项目,第二个项目应该是要返回的第二个项目等等。

标签: javascript function google-chrome-extension fetch


【解决方案1】:

Fetch(和许多其他异步方法)的运行时间不确定。这就是为什么它们是异步的,它们依赖于一些可能需要可变时间的外部资源。

您无法确保响应顺序与调用顺序相同。你可以做的是在sendResponse调用中发送request.itemURL作为第二个参数,然后修改你的回调以使用它,例如

内容.js

...
(price, url) => {
    console.log(`${url}: price: ${price}`);
});
...

Background.js

...
sendResponse(price.items_list[skinFullName].price["7_days"].average, request.itemURL);
...

这将确保您可以跟踪哪些商品的价格。

如果您确实需要它们按特定顺序排列,则需要等到所有回调都被触发。这可以通过使用计数器并在调用sendMessage 之前递增,然后在回调中递减来完成。一些快速而肮脏的代码来做到这一点:

let counter = 0, results = {};
for(let i=0;i<35;i++){
    counter++;
    sendMessage(..., (price, url) => {
        counter--;
        results[url] = price;
        if(counter == 0){
            // finished all calls
            // print results
            console.log(results);
        }
    });
}

要直接回答所提出的问题:您必须为sendMessage 创建一个返回承诺的包装器,然后使用let results = await sendMessageWrapper(...) 之类的东西。正如this eslint rule 所解释的那样,在循环中使用 await 是一种反模式。

【讨论】:

  • 我觉得这可能是最好的方法,但我更喜欢 priceNumber 而不是 itemURL,因为我稍后将使用它来识别它们。但是,当我使用您的代码时,它只返回 undefined: price: undefined
  • 如果您想使用 priceNumber,您必须将其传递给后台页面并再次返回,或者您可以在循环中创建一个闭包以捕获 @987654330 时的值@函数被调用。您应该阅读闭包并在循环中使用回调来完全理解这里发生了什么。
  • 是的,我很确定我了解如何使用 priceNumber 的代码。我的意思是,即使我只是尝试了您的代码(没有 priceNumber),它也不起作用。我真的很感激你解释了一切!
猜你喜欢
  • 2021-12-20
  • 2020-08-01
  • 2022-01-27
  • 1970-01-01
  • 1970-01-01
  • 2019-07-06
  • 1970-01-01
  • 2019-02-17
  • 2023-03-04
相关资源
最近更新 更多