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

An array of promises is returned when using axios in map function?

我正在通过这个 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 个函数的结果,所有 return 个承诺作为你的 .map() 结果。这就是代码应该如何工作的。等待您使用它没有完成任何事情。如果您改为使用 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()
}

他们都 return 承诺解决任何 axios.get() 解决的问题。第一个 return 是一个承诺,因为它在一个异步函数中,所有异步函数 return 在它们到达第一个 await 时是一个承诺。第二个 return 是一个承诺,因为您直接 returning axios.get() 承诺。无论哪种方式,他们都 return 解决同一件事的承诺。

因此,一般来说 return await fn()return fn() 相比对您没有帮助,因此不推荐使用。然后,一旦您在那里停止使用 await,您就不再需要 async 来进行 .map() 回调。