2014-10-23 3 views
0

Вот что я пытаюсь сделать. Мне нужно сделать предварительную обработку объекта JSON. Чтобы сделать это, мне нужно пройти через каждый элемент, выполнить обещание для нового человека, если для этого человека нет идентификатора, а затем обновить этот элемент в списке.Понимание Javascript Promises - Просто хочу пояснения

Пример:

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

Первый элемент не имеет лица идентификатор, так что я собираюсь создать обещание, создать человека в базе данных, а затем обновить этот элемент и заменить «John Doe 'с personId. Второй элемент уже имеет идентификатор и не нужно заходить в базу данных для создания нового человека.

Этот код работает так, как есть. Проблема в том, что я пытаюсь сделать цикл for, и мне нужно синхронное обещание. У меня проблемы. Как я могу использовать цикл и иметь обещание называется или условно не обрабатывать обещание, а логика работает синхронно?

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

Логика не может работать синхронно при использовании асинхронных операций. Вы должны ввести код для асинхронных ответов. Накопите список обещаний, а затем используйте что-то вроде 'Q.all()' для контроля всех обещаний и вызова своего обратного вызова, когда все будет сделано. – jfriend00

+0

Вы не должны этого делать, потому что 'loop' и' push' являются синхронными операциями – monkeyinsight

ответ

1

Мне нужен synchrounous обещание. Я в беде

Вы не можете. 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 
}); 
+0

Удивительно, я не знал, что карта может быть использована именно так. Большой! –

Смежные вопросы