理解Javascript承诺 - 只想要解释

时间:2014-10-23 02:51:40

标签: javascript node.js promise q

这是我尝试做的事情。我需要对JSON对象进行一些预处理。为了做到这一点,我需要循环遍历每个元素,如果没有该人的id,则为新人做一个承诺,然后在列表中更新该元素。

示例:

participant:[{
    person:{
        firstName: 'john'
        lastName: 'Doe'
    },
    role: 'Plumber'
}, {
    person: '12345a9j09kf23f3'
    role: 'Window Washer'
}]

第一个元素没有人名,所以我要创建一个承诺,在数据库中创建人,然后更新该元素并替换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

1 个答案:

答案 0 :(得分:1)

  

我需要一个同步的承诺。我遇到了麻烦

你做不到。 Promises are inherently asynchronous。它们不是使异步任务同步执行的工具,它们是顺利处理异步结果的抽象。

您可以做的是为每个参与者触发一个任务,如果在那里不明显,则在数据库中异步创建它,并让它们并行运行。然后,您可以轻松地获取所有结果(对它们的承诺)并等待所有结果,以便您对所有任务的所有结果都有承诺 - 这就是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
});