在 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()
回调。
我正在通过这个 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()
回调。