2016-05-31 261 views
7

我正在嘗試用Promise編寫此代碼。但我不知道如何在諾言和循環中寫諾言。 我試圖這樣想,但insertBook函數變得異步。 如何同步獲取bookId?承諾內承諾

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

避免['Promise'構造反模式](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-建築反模式和如何對避免-吧)! – Bergi

回答

0

假設insertBook返回一個承諾,你可以做

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

謝謝你的幫助。我做到了!。但我還有一個問題。這個'PEOPLE'表具有允許NULL的列'book_id'。和'書'表有colum'people_id',它不允許NULL。所以我想在插入People之後,我必須插入Book數據。 –

+0

我一次插入了人員數據。但是我應該每次插入這些人員數據以便使用插入到Book表中的book_id? –

+0

@你可以在方法'insertBook'中做到這一點,我要做的就是檢查一個id爲people_id的人是否存在,如果不存在,那麼先創建它,然後執行事務插入書 –

1

你不需要得到BOOKID同步,你可以異步正確處理它。此外,您可能希望所有書籍插入順序發生,因此我重構了Promise.all部分。 (這樣做只是爲了給你一個想法,如果允許並行插入,Promise.all應該可以正常工作)。此外,我認爲你不應該使用Promise.bind。說實話,我甚至不知道它做了什麼,肯定的一件事:它不符合標準的承諾。因此,這裏是一個例子,我怎麼想它應該工作:

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"); 
    }); 
}