说我需要找一些学生:
var promise = Student.find({..}).exec();
然后我需要访问单独引用它们的文档并将它们嵌入返回:
promise.then(function(students) {
var promises = [];
students.forEach(function(student) {
var groupPromise = Group.find({ studentRef: student._id }).exec();
groupPromise.then(function(group) {
...
student.embed = group;
return student;
});
promises.push(groupPromise);
});
return Promise.all(promises);
}).then(function(result) {
// expect result to be array of students, with { embed: group }
// instead result is array of groups
});
我在搞清楚承诺方面走了很长的路,但我错过了一些东西。我希望groupPromise.then(...)
能够在Promise.all(...)
被评估之前执行。由于情况显然不是这样,我需要一种方法来确保每个student
都嵌入了正确的group
。
答案 0 :(得分:2)
您放入数组并传递给Promise.all()
的承诺需要是groupPromise.then()
返回的结果,而不是groupPromise
本身。由于您使用的是groupPromise
,因此您无法看到groupPromise.then()
的结果。
请记住,每个.then()
都会返回一个新承诺,并且它会跟踪跟踪.then()
结果的新承诺。您没有将新承诺传递给Promise.all()
,因此您的结果未显示.then()
内发生的结果。
更改为:
promise.then(function(students) {
var promises = [];
students.forEach(function(student) {
var p = Group.find({ studentRef: student._id }).exec().then(function(group) {
...
student.embed = group;
return student;
});
promises.push(p);
});
return Promise.all(promises);
}).then(function(result) {
// result is array of students, with { embed: group }
});
仅供参考,使用.map()
代替.forEach()
时,这会更加精简:
promise.then(function(students) {
return Promise.all(students.map(function(student) {
return Group.find({ studentRef: student._id }).exec().then(function(group) {
...
student.embed = group;
return student;
});
}));
}).then(function(result) {
// result is array of students, with { embed: group }
});
而且,使用Bluebird's promise library中的Promise.map()
更简单一点:
promise.then(function(students) {
return Promise.map(students, function(student) {
return Group.find({ studentRef: student._id }).exec().then(function(group) {
...
student.embed = group;
return student;
});
});
}).then(function(result) {
// result is array of students, with { embed: group }
});
答案 1 :(得分:1)
基本上只有一件事是错的:
groupPromise.then(function(group) {
...
student.embed = group;
return student;
})
.then(function(student){
//this is what you want
});
groupPromise.then(function(group){
//this is what you do
});
groupPromise始终解析为<em>组。可以将groupPromise.then Promise解析为学生的Promise.all:
promises.push(groupPromise.then(function(group) {
...
student.embed = group;
return student;
}));
我将如何做到这一切:
promise.then(function(students) {
return Promise.all(students.map(function(student) {
return Group.find({ studentRef: student._id }).exec().then(function(group) {
...
student.embed = group;
return student;
});
}));
}).then(function(result) {
// expect result to be array of students, with { embed: group }
});
答案 2 :(得分:0)
我发现从变量声明中移除promise是有效的:
var promise = Student.find({..}).exec();
promise.then(function(students) {
var promises = [];
students.forEach(function(student) {
promises.push(
Group.find({ studentRef: student._id }).exec()
.then(function(group) {
...
student.embed = group;
return student;
})
);
});
return Promise.all(promises);
}).then(function(result) {
// now results is an array of students with { embed: group }}
});
我必须承认,我不知道它为什么会起作用。任何人吗?
编辑:找到解决方案。
正如你聪明的人所指出的,重要的是承诺的部分归还。推入promises
数组的承诺需要是.then()
返回的承诺。这些方法实际上只是一种语法上的类比,但我认为它们可能会为未来的读者提供启发。
方法一 - 完全推送promise.then():
var promises = [];
students.forEach(function(student) {
promises.push(Group.find().exec().then(function(group) {
student.embed
return student;
});
});
return Promise.all(promises);
不是特别漂亮。
方法二 - 将promise.then()分配给另一个变量:
var promises = [];
students.forEach(function(student) {
var groupPromise = Group.find().exec();
var embedPromise = groupPromise.then(function(group) {
student.embed
return student;
});
promises.push(embedPromise);
});
return Promise.all(promises);
比方法一更漂亮,但它实际上并不容易阅读。
方法三 - 正如jfriend00和Jonas w所建议的,.map()
很优雅:
promise.then(function(students) {
return Promise.all(students.map(function(student) {
return Group.find({ studentRef: student._id }).exec().then(function(group) {
...
student.embed = group;
return student;
});
}));
}).then(function(result) {
// expect result to be array of students, with { embed: group }
});