这是我要做的。我需要对JSON对象进行一些预处理。为了做到这一点,我需要循环遍历每个元素,如果没有新人员的id,则为该人员执行promise,然后更新列表中的该元素。
示例:
participant:[{
person:{
firstName: 'john'
lastName: 'Doe'
},
role: 'Plumber'
}, {
person: '12345a9j09kf23f3'
role: 'Window Washer'
}]
第一个元素没有person id,所以我将创建一个promise,在数据库中创建person,然后更新该元素并用personId替换"John Doe"。第二个元素已经有了id,不需要去数据库创建一个新的人。
这个代码按原样运行。问题是我正在尝试做一个for循环,我需要一个同步承诺。我有麻烦了。如何使用循环并调用promise,或者有条件地不处理promise和逻辑同步工作?
Box.create(box)
.then(function(data) {
_.forEach(participants, function (participant) {
//This promise will be executed asynchronously, possible to make it synchronous with the for loop?
if (typeof participant.person != 'undefined' && typeof participant.person.firstName != 'undefined') {
Person.create(participant.person).then(function (data) {
return Participant.create({}).then(function(data){
newParticipants.push(data);
})
});
} else {
participants.push(participant);
}
});
return Q(undefined);
}).then(function(){
// more logic
我需要一个同步的承诺。我遇到麻烦了
你不能。承诺本质上是异步的。它们不是使异步任务同步执行的工具,而是平滑处理异步结果的抽象。
您可以为每个参与者启动一个任务,如果不明显,则在数据库中异步创建它,并让它们并行运行。然后,您可以很容易地获得所有结果(承诺)并等待所有结果,这样您就可以获得所有任务的所有结果的承诺——这就是Q.all
所做的。
与其用foreach
"循环",如果您愿意的话,您总是应该用map
进行新的结果函数编程。它看起来是这样的:
Box.create(box).then(function(data) {
var participants = data.participants; // or so?
var promises = _.map(participants, function (participant) {
if (typeof participant.person != 'undefined' && typeof participant.person.firstName != 'undefined') {
return Person.create(participant.person)
.then(Participant.create)
// a promise for the new participant, created from the data that Person.create yielded
} else {
return Q(participant);
// a (fulfilled) promise for the participant that we already have
}
});
return Q.all(promises);
}).then(function(participants) {
// more logic, now with all (old+new) participants
});