【问题标题】:Am I using Promise.all correctly?我正确使用 Promise.all 吗?
【发布时间】:2022-01-08 06:55:27
【问题描述】:

我在我的代码中的很多地方都使用了它并且它有效。但在一个地方它没有给出任何错误,也没有给我想要的结果。当我向支持论坛展示我的代码时,他们建议“您错误地使用了 JS 对象/类“Promise”。”

任何人都可以指导我了解我的代码有什么问题吗 这是我的代码示例:

let charity = {};
      await Promise.all(
        charity = charityData.map(function( data ) {
              let address = data.zipCode
              let url = "https://maps.googleapis.com/maps/api/geocode/json?&address="+`'${address}'`+"&key=***Google geocoding Key***"; //client's Key
              let urlResponse = Backendless.Request.get(url)    
               // let latitude = urlResponse.results[0].geometry.location.lat;
               // let longitude = urlResponse.results[0].geometry.location.lng;
              //let updateCharitiesData = {'objectId': data.objectId, 'latitude':latitude, 'longitude':longitude};
              return urlResponse;
        })
      );
    return charity;

【问题讨论】:

  • 作为一般规则,我认为使用单数名词(慈善)来表示多个事物(在本例中是一组承诺)是一个坏主意。它表达了错误的东西。
  • 如果您解释了预期的结果和收到的结果,您的问题会更好。无论哪种方式,您都会得到解决问题的答案,但在这种情况下,有人会更好地解释为什么它对您不起作用,以及为什么他们的建议是在这种特定情况下的改进。
  • 它没有给我想要的结果” - 想要的结果是什么?!
  • let charity = {}; charity = charityData.map(…); return charity 真的很奇怪。您打算通过这种方式实现什么目标?

标签: javascript node.js arrays ecmascript-6 backendless


【解决方案1】:

如果您可以访问 Async/Await,我只需执行以下操作:

function getCharityData(charityData) {
let results = [];

for (let i = 0; i < charityData.length; i++) {
    let url = `https://maps.googleapis.com/maps/api/geocode/json?&address=${charityData[i].zipCode}&key=***Google geocoding Key***`;

    try {
        let result = await Backendless.Request.get(url);

        results.push(result);
    } catch (err) {
        console.log("Oh dear!");
    }
}

return results;

}

对于您的用例,当您拥有 Async/Await、老式的 for 循环和 await 时,无需使用任何 Promise 库(我个人更喜欢按顺序执行这种调用,而不是像 Promise 那样并行执行。当我查询外部 API 时 all 恳求。这也确保我们不会像 Promise.all 那样快速失败。)。

【讨论】:

  • 这个问题是因为它不使用Promise.all,所以请求是按顺序而不是并行发出的,这可能是OP试图做的。
  • Promise.all 不是“承诺库”
【解决方案2】:

几乎。假设 Backendless.Request.[method] 返回一个承诺,按照以下方式做一些事情会更正确:

async function getCharityData() {
    const charity = await Promise.all(charityData.map( async function(data) {
       const address = data.zipCode;
       const url =
        `https://maps.googleapis.com/maps/api/geocode/json?&address=${address}&key=***Google geocoding Key***`; //client's Key
       const urlResponse = await Backendless.Request.get(url);
       return urlResponse;
   }));

   return charity
}

Promise.all 需要一个数组作为其参数才能正常工作;在这里传递一个 Array.map 并将返回的值分配给慈善机构既可以确保您的 Promise.all 按预期运行,并且返回的数组是一个已解决的承诺数组。

【讨论】:

  • 这是对问题的回答,但如果您解释了为什么要这样做和/或为什么 OP 的代码在某些领域而不是其他领域有效,那将会大大改善。
  • 为什么将map回调改为async函数?
  • @Bergi 因为似乎 urlResponse 应该在等待获取请求。
  • 谢谢@Rodger,我已经更新了答案来解释。
  • @JoshuaBurleson 是的,但是您可以将其重命名为 const urlResponsePromise 并且只是 returned :-) 或者一起省略临时变量。
【解决方案3】:

我会这样做:

function getCharityData() {
    // `charity` is an array of Promises that will each resolve to 
    // a response.
    const charity = charityData.map((data) => {
        let address = data.zipCode;
        let url = 'https://maps.googleapis.com/maps/api/geocode'
        let urlResponse = Backendless.Request.get(url);
        return urlResponse;
    });
    return Promise.all(charity);
}
try {
    const charityData = await getCharityData();
} catch (e) {
    console.error(e);
}

这样,charityData 将是一个获取的响应数组。

在您的代码中,Promise.all() 的结果在返回之前从未分配给charity,这就是您想要的值。


【讨论】:

  • 并且可能还尝试/抓住等待。
  • 您能否描述一下您的示例与 OP 发布的内容之间的区别?
  • 完成@wahwahwah。谢谢。
  • 完成@lux。谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-02-28
  • 2015-06-25
  • 2011-08-07
  • 2011-09-26
  • 2019-05-03
  • 2016-03-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多