迭代数组并保存对象后回调

时间:2016-12-13 20:54:21

标签: javascript node.js express sequelize.js

我需要迭代一个数组并将每个对象保存到数据库中。

最后,我需要使用array所有已保存和失败的对象进行回调。

以下是我的代码:

exports.addList = (app, body, callback) => {
var savedObjects = []
var failedObjects = []

body.forEach((element, index) => {
    body[index] = _.pick(element, 'userAId','userBId')

    db.List.create(element).then((list) => {
        savedObjects.push(element)
         if (index == body.length - 1) {
            callback(savedObjects, failedObjects)
        }
    }).catch((error) => {
        if (error.name === "SequelizeUniqueConstraintError") {
            failedObjects.push(element)
             if (index == body.length - 1) {
            callback(savedObjects, failedObjects)
        }
    })
})
}

上面的代码有效。有没有更好的方法来实现这个目标?

2 个答案:

答案 0 :(得分:1)

我建议使用Promise.all()并行运行db.List.create()的方法,因为它会返回Promise。通过mapping body数组元素到Promises,您可以获得更好的性能,因为它们将并行运行(而不必跟踪complete计数)。

exports.addList = (app, body, callback) => {
  var savedObjects = [];
  var failedObjects = [];

  Promise.all(
    // map the array to return Promises
    body.map(element => {
      const list = _.pick(element, 'userAId','userBId');
      return db.List.create(list)
      .then(() => savedObjects.push(list))
      .catch((error) => {
        if (error.name === 'SequelizeUniqueConstraintError') {
          failedObjects.push(list)
        }
      })
    })
  )
  // when all Promises have resolved return the callback
  .then(() => callback(savedObjects, failedObjects));
}

答案 1 :(得分:0)

在您的示例中,您的完整回调将始终在第一个承诺完成后触发。这是因为create函数是异步的而周围的循环不是,因此循环将在您的第一个回调被触发时完成。

在您的方案中,这意味着elementindex将始终是循环中的最后一个。解决这个问题的一种方法是将你的承诺链转移到它自己的功能中。

在这个示例中,我使用了一个额外的标记来跟踪已完成的承诺的数量,以触发您的complete方法。

exports.addList = (app, body, callback) => {
  var savedObjects = []
  var failedObjects = []
  var complete = 0;

  function createElement(element){
    db.List.create(element).then((list) => {
        savedObjects.push(element)
    }).catch((error) => {
        if (error.name === "SequelizeUniqueConstraintError") {
            failedObjects.push(element)
        }
    }).finally(() => {
        complete++;
        if(complete == body.length) {
          callback(savedObjects, failedObjects)
        }
    });
  }

  body.forEach((element, index) => {
    body[index] = _.pick(element, 'userAId','userBId');
    createElement(element);
  })
}