2016-05-31 37 views
7

Próbuję napisać ten kod z obietnicy. ale nie wiem, jak napisać obietnicę w obietnicy i pętli. Starałem się myśleć w ten sposób, ale funkcji insertBook stać się asynchronicznie. Jak mogę uzyskać bookId synchronicznie?Obietnica wewnątrz obietnicy

update: function(items, quotationId) { 
    return new Promise(function(resolve, reject) { 
    knex.transaction(function (t) { 
     Promise.bind(result).then(function() { 
     return process1 
     }).then(function() { 
     return process2 
     }).then(function() { 
     var promises = items.map(function (item) { 
      var people = _.pick(item, 'familyName', 'firstNumber', 'tel'); 
      if (item.type === 'book') { 
      var book = _.pick(item, 'name', 'bookNumber', 'author'); 
      var bookId = insertBook(t, book); 
      var values = _.merge({}, people, {quotation: quotationId}, {book: bookId}); 
      } else { 
      var values = _.merge({}, people, {quotation: quotationId}); 
      } 
      return AModel.validateFor(values); 
     }); 
     return Promise.all(promises); 
     }).then(function(items) { 
     var insertValues = items.map(function (item) { 
      return People.columnize(item); 
     }); 
     return knex('people').transacting(t).insert(insertValues); 
     }).then(function() { 
     return process5 
     }).then(function() { 
     ........... 

     }).then(function() { 
     t.commit(this); 
     }).catch(t.rollback); 
    }).then(function (res) { 
     resolve(res); 
    }).catch(function(err) { 
     reject(err); 
    }); 
    }); 
} 

function insertBook(t, book){ 
    return Promise.bind(this).then(function() { 
    return Book.columnizeFor(book); 
    }).then(function (value) { 
    return knex('book').transacting(t).insert(value, "id"); 
    }); 
} 
+0

Unikaj [ 'Promise' konstruktor antywzorzec projektowy] (https://stackoverflow.com/q/23803743/1048572?What-is-the-promise- konstrukcja-antipattern-i-jak-unikać-to)! – Bergi

Odpowiedz

0

Zakładając, że insertBook zwraca obietnica można zrobić

var people = _.pick(item, 'familyName', 'firstNumber', 'tel'); 
if (item.type === 'book') { 
    var book = _.pick(item, 'name', 'bookNumber', 'author'); 
    return insertBook(t, book) 
    .then(bookId => _.merge({}, people, {quotation: quotationId}, {book: bookId})) 
    .then(AModel.validateFor) 
} else { 
    return Promise.resolve(_.merge({}, people, {quotation: quotationId})) 
    .then(AModel.validateFor) 
} 
+0

Dziękuję za pomoc. Ja to zrobiłem!. ale mam jeszcze jedno pytanie. ta tabela "LUDZIE" zawiera kolumnę "book_id", która dopuszcza NULL. a tabela "Book" ma colum "people_id", który nie pozwala na NULL. więc pomyślałem, że po wstawieniu People muszę wstawić dane Book. –

+0

Wprowadziłem dane osób naraz. ale czy należy wstawiać te dane osób za każdym razem, aby używać book_id, który został wstawiony do tabeli Book? –

+0

@ 通 り す が り の お っ さ ん można zrobić w metodzie 'insertBook', co chciałbym zrobić, to sprawdzić, czy osoba z id' people_id' istnieje, jeśli nie to go najpierw stworzyć, a następnie wykonaj transakcji wstawić książkę –

1

Nie musisz dostać bookid synchronicznie, można go obsługiwać asynchronicznie poprawnie. Ponadto, możliwe jest, aby wszystkie wstawki ty book zdarzyć sekwencyjnie, więc refactored się Promise.all część. (Zrobione, że po prostu dać ci pomysł. Promise.all powinien działać dobrze, jeśli równolegle wstawki są dozwolone). Ponadto myślę, że nie powinieneś używać Promise.bind. Szczerze mówiąc nie wiem nawet, co robi, jedno na pewno: nie działa ze standardowymi obietnicami. Więc tutaj jest przykładem, jak myślę, że to powinno działać:

update: function(items) { 
    return new Promise(function(resolve) { 
    knex.transaction(function (t) { 
     resolve(Promise.resolve().then(function() { 
     return process1; 
     }).then(function() { 
     return process2; 
     }).then(function() { 
     var q = Promise.resolve(), results = []; 
     items.forEach(function (item) { 
      q = q.then(function() { 
      var book = _.pick(item, 'name', 'bookNumber', 'author'); 
      return insertBook(t, book); 
      }).then(function(bookId) { 
      var people = _.pick(item, 'familyName', 'firstNumber', 'tel'); 
      var values = _.merge({}, people, {book: bookId}); 
      return AModel.validateFor(values); 
      }).then(function(item) { 
      results.push(item); 
      }); 
     }); 
     return q.then(function() { 
      return results; 
     }); 
     }).then(function(items) { 
     return process4 
     }).then(function() { 
     t.commit(result); 
     }).catch(function(e) { 
     t.rollback(e); 
     throw e; 
     })); 
    }); 
    }); 
} 

function insertBook(t, book){ 
    return Promise.resolve().then(function() { 
    return Book.columnizeFor(book); 
    }).then(function (value) { 
    return knex('book').transacting(t).insert(value, "id"); 
    }); 
}