我目前正在尝试使用 React.js 开发仪表板应用程序。 我正在尝试填充对象数组并将它们映射到列表中。
对于每个对象,我必须对我的服务器进行 axios GET 调用才能获取所有数据。 当我尝试从数组中读取对象时,我得到的顺序与预期的顺序不同。首选输出是数组中的对象按日期时间排序。
我的猜测是,这与线程有关,并且第一个完成的请求将在其他请求之前插入。
有谁知道我现在正在做的事情是否有更好的方法?或者如果我忘记了什么。
这是我执行逻辑的主要组件
const [shipments, setShipments] = useState([]);
async function createRows(shipmentId){
// The incoming id's are in correct order
const details = await getShipmentDetails(shipmentId);
// From this point on the responses are in a different order each time it's ran
let row = {
shipmentId: details.shipmentId,
shipmentReference: details.shipmentReference,
shipmentDateTime: details.shipmentDateTime,
shipmentItems: details.shipmentItems,
}
if(shipments.map(s => s.shipmentId).indexOf(row.shipmentId) == -1){
setShipments(rows => [...rows, row])
}
}
async function retrieveShipments(){
const amount = 5;
await connectToBol();
let allShipments = await getShipments();
allShipments.splice(amount, (allShipments.length-amount + 1))
if(allShipments.length > 0){
allShipments.forEach(async shipment => {
await createRows(shipment.shipmentId);
})
}
}
useEffect(() => {
retrieveShipments()
}, []);
这是执行axios请求的方法
export async function getShipmentDetails(shipmentId){
const response = await axios.get(`${baseUrl}/shipments/${shipmentId}`,{
headers: {
'Authorization': 'Bearer ' + <token>
}
})
.catch((error) => {
console.log('Error: ', error);
});
return response.data;
}
我不会专注于如何解决您的问题,我将专注于标题中提出的问题,如果可以的话:
为什么我会得到一个随机排序的数组?
好吧,情况是这样的:您正在使用
forEach
并进行一堆 api 调用
allShipments.forEach(async shipment => {
await createRows(shipment.shipmentId);
})
这可能并不明显,但仅仅因为您在
await
循环中使用了 .forEach
并不意味着每个项目都按顺序处理 - 事实上,发生的情况是所有 createRows
调用都同步排队.
如果我这样做
[1,2,3].forEach(v => someAsyncFunc(v));
,它会调用someAsyncFunc(1)
,然后调用someAsyncFunc(2)
,然后调用someAsyncFunc(3)
,但是调用2和3而不需要等待1完成。
因此,如果奇迹般地
someAsyncFunc(2)
在 someAsyncFunc(1)
之前完成,您最终可能会得到乱序结果。我相信这就是发生在你身上的事情,也是你问这个问题的原因。
如果您希望
someAsyncFunc(2)
在 someAsyncFunc(1)
完成后运行,则不要执行 forEach
循环,而是执行 for...of
循环
for (let x of [1,2,3]) {
await someAsyncFunc(x);
}
那么,只有在 1 完成后,2 才会开始。