javascript 为什么我得到一个随机有序数组?[复制]

jq6vz3qz  于 12个月前  发布在  Java
关注(0)|答案(1)|浏览(76)

此问题在此处已有答案

How to sort an object array by date property?(25个回答)
Using async/await with a forEach loop(34个回答)
6小时前关闭
我目前正在尝试在React.js中开发一个 Jmeter 板应用程序。我正在尝试填充一个对象数组并将它们Map到列表中。
对于每个对象,我都必须对服务器进行axios GET调用以获取所有数据。当我试图从数组中读取对象时,我得到的顺序与我应该得到的顺序不同。首选输出是数组中的对象按DateTime排序。
我的猜测是,它与线程有关,第一个完成的请求将在其他请求之前插入。
有没有人知道有没有更好的方法来做我现在正在做的事情?或者如果我忘记了什么。
这是我执行逻辑的主要组件

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; 
}


下面是我当前获得的输出

7qhs6swi

7qhs6swi1#

我不打算专注于如何解决你的问题,我将专注于标题中提出的问题,如果可以的话:
为什么我得到的是一个随机有序数组?
现在的情况是:您正在使用forEach并进行大量API调用

allShipments.forEach(async shipment => { 
      await createRows(shipment.shipmentId);
    })

字符串
这可能并不明显,但仅仅因为您在.forEach循环中使用了await并不意味着每个项目都按顺序处理-实际上,发生的是所有createRows调用都同步排队。
如果我执行[1,2,3].forEach(v => someAsyncFunc(v));,它会调用someAsyncFunc(1),然后是someAsyncFunc(2),然后是someAsyncFunc(3),但是2和3会被调用,而不会等待1完成。
所以,如果奇迹发生在someAsyncFunc(1)之前,someAsyncFunc(2)完成了,你可能会得到乱序的结果,这就是我相信发生在你身上的事情,也是你问这个问题的原因。
如果希望someAsyncFunc(2)someAsyncFunc(1)完成后运行,则不执行forEach循环,而执行for...of循环

for (let x of [1,2,3]) {
    await someAsyncFunc(x);
}


然后,只有在% 1完成后,% 2才会开始。

相关问题