为什么我会得到一个随机排序的数组?

问题描述 投票:0回答:1

我目前正在尝试使用 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; 
}

下面是我当前得到的输出

javascript reactjs arrays sorting axios
1个回答
0
投票

我不会专注于如何解决您的问题,我将专注于标题中提出的问题,如果可以的话:

为什么我会得到一个随机排序的数组?

好吧,情况是这样的:您正在使用

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 才会开始。

© www.soinside.com 2019 - 2024. All rights reserved.