我正在创建一个待办事项应用程序,我希望每个待办事项列表都具有唯一的名称。每个用户都有一个待办事项列表数组。传入的POST请求(用于创建新列表)已附加了用户对象,因此我可以使用const userLists = req.user.list
获取数组。这个(如果我用控制台登录的话)是每个列表_id
。
我试图遍历这些对象以获得列表对象,并测试名称以查看其是否等于req.body.name
以确保唯一性。
我宁愿保留函数async
,因为我在下面有更多逻辑,也不希望嵌套太多回调函数。
我尝试过
exports.createList = async (req, res) => {
const usersLists = req.user.lists;
let proms = [];
let found = false;
userLists.map(list => {
const listObj = List.findOne({_id : list});
if(listObj.name === req.body.name)
found = true
})
(other code below to create list)
,还尝试await List.findOne()
,但我无法async
地图。
我相信代码已经超出了这个范围,因此found
永远都不是。
然后我在网上看到一些使用Promise.all()
的东西,所以我尝试了这个:
let proms = []
usersLists.map(listId => {
proms.push(List.findOne({_id: listId}, "name").exec());
});
await Promise.all(proms.map(p => {
if(p.name == req.body.name)
found = true;
}))
,但是下面的代码仍然运行,并且列表已创建。如果我console.log(proms)
,则它由[object Promise]数组组成。
对我来说这还很新,我要做的就是遍历一个列表ID的数组,获取列表对象并测试以查看任何列表名称是否等于我的新列表名称要创建(并返回错误)
任何帮助将不胜感激。谢谢
答案 0 :(得分:1)
让我在这里解决问题
let proms = []
usersLists.map(listId => {
proms.push(List.findOne({_id: listId}, "name").exec());
});
await Promise.all(proms.map(p => {
if(p.name == req.body.name)
found = true;
}))
首先,
let proms = []
usersLists.map(
将返回一个新数组,因此您不需要let proms = []
并将其压入。
您也可以在地图回调中使用async/await
。
相反,您可以做的是
const promises = usersLists.map(async listId => {
const prom = await List.findOne({_id: listId}, "name").exec();
if(p.name == req.body.name) // I put this here so we don't have to make another loop
found = true;
});
地图循环完成后,promises
将是一个承诺数组。因此,为了使javascript等待所有这些承诺,您现在将使用Promise.all(promises)
。
为此,这就是方法
await Promise.all(promises);
接下来是最终输出
const promises = usersLists.map(async listId => {
const prom = await List.findOne({_id: listId}, "name").exec();
if(p.name == req.body.name)
found = true;
});
await Promise.all(promises);
答案 1 :(得分:1)
所有响应,即使它们是有效的,也倾向于在异步操作中更改外部变量,这绝对是你不应该做的,永远不要做。
从理论上讲,它应该简化为(未经测试):
const promises = usersLists.map(listId => List.findOne({_id: listId}, "name"));
const isFound = await Promise.all(promises).then(arr => {
//check your array
// return true or false
});
console.log("Result...", isFound);
顺便说一句,您始终可以查询mongo,而无需执行一堆findOne。通常,您可以在一个电话中进行通话,或者至少将其分组在较少的通话中。
答案 2 :(得分:0)
Promise.all
接受包含promise的数组,并在它们全部完成后进行解析。请阅读here
假设以上代码在async
函数中执行
let found = false;
let proms = usersLists.map(listId => List.findOne({
_id: listId
}, "name").exec());
let userDetails = await Promise.all(proms);
for (let index = 0; index < userDetails.length; index++) {
const user = userDetails[index]
if (user.name === req.body.name) {
found = true
}
}
答案 3 :(得分:0)
我看到了,试试这个吗?
let found = false
// proms:users all message in List model
let proms = await Promise.all(
// usersLists: user id message ['', '']
usersLists.map(async listId => {
// List: user model, listObj {_id: '', name: ''}
const listObj = await List.findOne({_id : listId});
if(listObj.name == req.body.name){
found = true
}
return listObj
});
)
// other code