简体   繁体   中英

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

I am mapping through this dummyAssests array and want to create a new array of objects based on the axios response called newAssetArray. But when I console.log the newAssetArray it just contains an array of 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]);

Console:

在此处输入图像描述

Yes, that is expected. Use Promise.all() to wait for all the promises to resolve. .map() itself is not promise aware so it does not "wait" for each individual iteration of its loop to resolve before going onto the next one. So, you have the result of calling N async functions which all return a promise as your .map() result. That is how the code is supposed to work. The await you are using it not accomplishing anything. If you use a for loop instead (which is promise-aware, then your loop will be sequenced.

Here's how you could use Promise.all() to get the results:

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]);

Or, you might find this implementation a bit simpler to follow:

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]);

Also, note that a structure such as:

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

does nothing different than just:

async someFunction() {
    return axios.get()
}

They both return a promise that resolves to whatever axios.get() resolves to. The first returns a promise because it's in an async function and ALL async functions return a promise at the point they hit the first await . The second returns a promise because you're directly returning the axios.get() promise. Either way, they both return a promise that resolves to the same thing.

So, in general return await fn() is not helping you vs just return fn() and is not recommended. Then, once you stop using await there, you don't need async for that .map() callback anymore either.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM