在map函数中使用axios时返回一个promise数组?

Posted

技术标签:

【中文标题】在map函数中使用axios时返回一个promise数组?【英文标题】:An array of promises is returned when using axios in map function? 【发布时间】:2021-12-30 09:24:04 【问题描述】:

我正在通过这个 dummyAssests 数组进行映射,并希望根据名为 newAssetArray 的 axios 响应创建一个新的对象数组。但是当我 console.log 时 newAssetArray 它只包含一个 Promises 数组......

 useEffect(() => 
    let newAssetArray = dummyAssets.map(async function (asset) 
      return await axios
        .get(currrentPrice(asset.asset_id))
        .then((response) => 
          let cp = response.data.market_data.current_price.eur;
          let value = Number(cp) * Number(asset.amount);
          return  ...asset, value: +value ;
        )
        .catch((error) => console.log(error.response.data.error));
    );
    setAssets(newAssetArray);
    console.log(newAssetArray);
  , [dummyAssets]);

控制台:

【问题讨论】:

是的,这是意料之中的。使用Promise.all() 等待所有的承诺解决。 .map() 本身没有承诺意识,因此它不会“等待”其循环的每个单独迭代在进入下一个迭代之前解决。所以,你有调用 N 个async 函数的结果,它们都返回一个承诺作为你的.map() 结果。这就是代码应该如何工作的方式。 await 您正在使用它没有完成任何事情。如果您改用 for 循环(这是可感知的,那么您的循环将被排序。 谢谢。你能举例说明如何使用 Promise.all() 吗? 【参考方案1】:

是的,这是意料之中的。使用Promise.all() 等待所有的承诺解决。 .map() 本身不具备承诺意识,因此它不会“等待”其循环的每个单独迭代解决,然后再进行下一个迭代。所以,你有调用 N 个async 函数的结果,它们都返回一个承诺作为你的.map() 结果。这就是代码应该如何工作的方式。您正在使用它的 await 没有完成任何事情。如果您改用 for 循环(它可以感知承诺,那么您的循环将被排序。

以下是使用Promise.all() 获取结果的方法:

useEffect(() => 
    Promise.all(dummyAssets.map(function(asset) 
        return axios
            .get(currrentPrice(asset.asset_id))
            .then((response) => 
                let cp = response.data.market_data.current_price.eur;
                let value = Number(cp) * Number(asset.amount);
                return  ...asset, value: +value ;
            ).catch((error) => 
                console.log(error.response.data.error)
                throw error;
            );
    )).then(newAssetArray => 
        console.log(newAssetArray);
        setAssets(newAssetArray);
    ).catch(err => 
        // do something to handle the error here
    );
, [dummyAssets]);

或者,您可能会发现这个实现更简单:

useEffect(async () => 
    try 
        const newAssetArray = await Promise.all(dummyAssets.map(async function(asset) 
            const response = await axios.get(currrentPrice(asset.asset_id));
            const cp = response.data.market_data.current_price.eur;
            const value = Number(cp) * Number(asset.amount);
            return  ...asset, value: +value ;
        ));
        console.log(newAssetArray);
        setAssets(newAssetArray);
     catch (e) 
        // do something to handle the error here
        console.log(e);
    
, [dummyAssets]);

另外,请注意以下结构:

async function someFunction() 
    return await axios.get()

没有什么不同,只是:

async someFunction() 
    return axios.get()

它们都返回一个可以解析为 axios.get() 解析的任何内容的承诺。第一个返回一个承诺,因为它在一个异步函数中,并且所有异步函数在它们遇到第一个await 时都返回一个承诺。第二个返回一个承诺,因为您直接返回 axios.get() 承诺。无论哪种方式,它们都返回一个解决相同问题的承诺。

所以,一般return await fn() 对您没有帮助,而只是return fn(),不推荐。然后,一旦你停止在那里使用await,你就不再需要async 来进行.map() 回调。

【讨论】:

以上是关于在map函数中使用axios时返回一个promise数组?的主要内容,如果未能解决你的问题,请参考以下文章

TypeError:使用axios获取数据时language.map不是函数

如何使用带有 (axios/classhooks) 的 map 函数从 API 中读取

axios 请求数据,返回数据 data为空怎么办

尝试将 JSON 传递给 Vue 时获取 .map() 不是函数

axios 学习笔记

如何将 map() 与来自 axios 响应的数据一起使用?