Promise内部的Promise

9

我正在尝试使用Promise编写代码。但是我不知道如何在Promise内部和循环中编写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");
  });
}

1
避免使用Promise构造函数反模式! - Bergi
2个回答

1

您不需要同步获取bookid,可以正确地异步处理它。此外,可能您希望所有的book插入按顺序发生,因此我重构了Promise.all部分。(只是为了给您一个想法)。如果允许并行插入,则Promise.all应该可以正常工作。此外,我认为您不应该使用Promise.bind。说实话,我甚至不知道它是做什么的,有一件事情是确定的:它不适用于标准Promise。所以这里是我认为它应该如何工作的示例:

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

0
假设insertBook返回一个Promise,你可以这样做:
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)
}

谢谢你的帮助。我做到了!但是我还有一个问题。这个“PEOPLE”表有一个允许为空的“book_id”列。而“Book”表具有不允许为空的“people_id”列。所以我认为在插入People数据后,我必须插入Book数据。 - 通りすがりのおっさん
我一次性插入了People数据。但是,我是否应该每次为在Book表中插入的book_id插入这些People数据? - 通りすがりのおっさん
@通りすがりのおっさん 你可以在 insertBook 方法中实现这个功能,我会先检查是否存在 id 为 people_id 的人员,如果不存在,则先创建该人员,然后再执行事务来插入书籍。 - Mauricio Poppe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接