node.js - 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 中。我应该如何处理?
解决方案
不,Promise.all
也map
不会改变数组的顺序。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
的元素。undefined
null
另一种可能性如下
for (let item of somelist) {
let u = await User.findById(item.some);
if (u) arr.push(u);
}
但这是序列化您的请求并一个接一个地执行。所以这可能会浪费大量时间等待一些外部结果(网络、数据库、磁盘......)
推荐阅读
- css - 如何在 Gatsby 中禁用内联 CSS?
- arrays - 如何在不使用 .reversed() 的情况下使用循环填充具有与语言相同项的新数组?
- java - 如何在java中将矩阵添加到ArrayList
- swift - 在 Xcode 模拟器上运行预览
- terraform - 如何从 terraform 列表中选择元素
- c - 需要在多个数组中显示前 3 个最高数字
- android - 成功登录后如何使“登录布局”更改布局
- javascript - 路由的组件必须是 React native expo 中的 react 组件错误
- dataweave - 将带有父 ID 和子数组的 JSON 转换为 Dataweave 中子数组中每个元素一个 json 对象的数组
- java - 使用鼠标和键盘在 3D 空间中移动 [JavaFX3D]