【问题标题】:Using async await when mapping over an arrays values映射数组值时使用异步等待
【发布时间】:2017-09-17 16:14:17
【问题描述】:

我正在尝试将新的 async/await 与对一组值的映射结合使用。 但是我有点困惑,在这种特定情况下,它前面应该有 await 关键字。

关于这个话题的信息还不是很多。

我试图简单地将 map() 和值数组放在 Axios get() 请求中,然后返回一个 then() 值,该值被添加到 map() 函数返回的数组中.

这是我现在的代码:

async function get_prices (arrayOfDates, crypto, FIAT) {
  // I tried this way (return value can be found below)
  let arry_of_prices = arrayOfDates.map(async function(date){
    let a = await fetch_data(date, crypto, FIAT)
    return a
  });

  // And this way (return value can be found below)
  let arry_of_prices = await arrayOfDates.map(date => fetch_data(date, crypto, FIAT));
} 

const fetch_data = (timestamp, crypto, FIAT) => {
  axios.get(`https://min-api.cryptocompare.com/data/pricehistorical?fsym=${crypto}&tsyms=${FIAT}&ts=${timestamp}`)
  .then(function (response) {
    return Object.values(response.data).map(key => Object.values(key))[0][0]
  })
  .catch(function (error) {
    console.log(error);
  });
}

let arr = [1468965600, 1469052000, 1469138400,1469484000]

get_prices(arr, "BTC", "USD").then(arr => console.log(arr))

第一次尝试返回 4 个 resolved 承诺,但值是 undefined。 而第二个返回一个包含 4 个undefined 的数组。

有没有人知道如何构造它,以便map() 等到函数被解析然后将值添加到数组中?

【问题讨论】:

    标签: javascript arrays asynchronous async-await


    【解决方案1】:

    map 对承诺一无所知,因此当您将async 回调与map 一起使用时,您将得到一组承诺,而不是值。如果你想要一个在所有这些承诺都解决后会解决的承诺,你可以使用Promise.all

    但是,在您的情况下,您不需要异步函数,因为您在回调中使用了 fetch_data。您需要修改fetch_data,使其返回来自axios.get 的承诺(并删除catch 处理程序):

    const fetch_data = (timestamp, crypto, FIAT) => {
      return axios.get(`https://min-api.cryptocompare.com/data/pricehistorical?fsym=${crypto}&tsyms=${FIAT}&ts=${timestamp}`)
      .then(function (response) {
        return Object.values(response.data).map(key => Object.values(key))[0][0]
      });
    }
    

    (这是承诺的规则之一:如果您要返回承诺,则不会处理来自它的拒绝[除非您想将它们转换为不同的拒绝,或者如果您可以有效地将它们转换为解决方案]。如果你返回承诺,你确实处理拒绝。)

    现在你已经有了一个承诺,所以你在map 中使用它(不需要async):

    async function get_prices (arrayOfDates, crypto, FIAT) {
      let arr_of_price_promises = arrayOfDates.map(function(date){
        let a = fetch_data(date, crypto, FIAT)
        return a
      });
      return Promise.all(arr_of_price_promises);
    }
    

    请注意,我从 fetch_data 前面删除了 await。我们直接返回fetch_data的promise,然后等待他们。

    或者用箭头函数:

    async function get_prices (arrayOfDates, crypto, FIAT) {
      let arr_of_price_promises = arrayOfDates.map(date => fetch_data(date, crypto, FIAT));
      return Promise.all(arr_of_price_promises);
    }
    

    【讨论】:

    • 但这不仍然返回一个已解决的承诺,具有未定义的价值吗?
    • @Jousi:不,它返回一个承诺,当所有fetch 承诺解决时将解决(或者当第一个fetch 承诺拒绝时拒绝)。它使用一个数组进行解析,该数组是每个 fetch 承诺的解析值,按照将这些承诺提供给 Promise.all 的顺序。
    • @Jousi:哦,抱歉,您使用的是自己的fetch_data,而不是fetchfetch_data需要修改一下,我补充一下。
    • 是的,我也注意到了,调整了 :) 谢谢 TJ!
    • @Jousi: :-) 更新了答案以显示对fetch_data 的操作。很高兴有帮助!
    猜你喜欢
    • 2020-09-26
    • 2021-03-06
    • 1970-01-01
    • 2019-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-11
    • 2020-03-13
    相关资源
    最近更新 更多