我需要迭代一个数组并将每个对象保存到数据库中。
最后,我需要使用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)
}
})
})
}
上面的代码有效。有没有更好的方法来实现这个目标?
答案 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
函数是异步的而周围的循环不是,因此循环将在您的第一个回调被触发时完成。
在您的方案中,这意味着element
和index
将始终是循环中的最后一个。解决这个问题的一种方法是将你的承诺链转移到它自己的功能中。
在这个示例中,我使用了一个额外的标记来跟踪已完成的承诺的数量,以触发您的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);
})
}