首页 > 解决方案 > Promise.all 对象映射搞乱了数据的排序

问题描述

我有一个返回对象的节点 api,但返回的对象并不总是相同的顺序。我是这样做的:

const somelist = await Model.find({condition blah blah})
                        .sort({created_at: -1})
                        .select('some fields');
if(!somelist){
    res.status(500).json({ success: false });
}else{
    let arr = [];
    await Promise.all(somelist.map(async (item) => {
        let user = await User.findById(item.some);
        if(user) {
            arr.push(item);
        }
    }));

    console.log(arr)
    res.status(200).json(arr);
}

最初的显示是 1, 2, 3,但有时会变成 2, 1, 3,但很少见。因为我在我的 somelist 中添加了一个排序功能,所以问题可能出在 promise 中。我应该如何处理?

标签: node.js

解决方案


不,Promise.allmap不会改变数组的顺序。Promise.all保证以与您输入的 promisearray 相同的顺序返回结果。

但是:无法保证解决承诺的顺序,因此arr.push()可以以任何顺序发生,因此您可能会收到不同的结果。所以你可以这样做

let arr = (await Promise.all(somelist.map(i => User.findById(i.some)))
  .filter(r => !!r)

假设User.findById()返回一个承诺,则somelist.map(...)返回一个承诺数组,您可以await使用Promise.all. Promise.all解决后,您可以取出所有返回 a或结果filter的元素。undefinednull

另一种可能性如下

for (let item of somelist) {
  let u = await User.findById(item.some);
  if (u) arr.push(u);
}

但这是序列化您的请求并一个接一个地执行。所以这可能会浪费大量时间等待一些外部结果(网络、数据库、磁盘......)


推荐阅读