gpt4 book ai didi

bluebird - 中断 Bluebird .each() 进程

转载 作者:行者123 更新时间:2023-12-02 21:46:07 26 4
gpt4 key购买 nike

我正在从异步转换为 Bluebird,但不知道如何打破循环

这是我想要实现的目标:

  1. 循环数据数组。
  2. 对于每个项目,检查它是否存在于数据库中。
  3. 一个项添加到数据库(第一个不存在的项),然后退出.each()循环。

任何帮助将不胜感激。

最佳答案

Bluebird 没有针对该类型操作的内置函数,并且适应 Promise 迭代模型有点困难,因为迭代器返回单个值(Promise),这并没有真正给您提供通信的机会返回成功/错误并停止迭代。

使用拒绝来停止迭代

您可以使用Promise.each() ,但是您必须使用编码拒绝才能停止迭代,如下所示:

var data = [...];

Promise.each(data, function(item, index, length) {
return checkIfItemExists(item).then(function(exists) {
if (!exists) {
return addItemToDb(item).then(function() {
// successfully added item to DB
// lets reject now to stop the iteration
// but reject with a custom signature that can be discerned from an actual error
throw {code: "success", index: index};
});
}
})
}).then(function() {
// finished the iteration, but nothing was added to the DB
}, function(err) {
if (typeof err === "object" && err.code === "success") {
// success
} else {
// some sort of error here
}
});

如果您必须定期使用此结构,则可以将其放入可重用的函数/方法中。您只需对被拒绝的 Promise 采用约定,该约定实际上只是成功地停止迭代,而不是实际的错误。

这看起来确实是一个有趣的需求,而且并非不常见,但我还没有看到任何带有 Promises 的特定定义结构来处理此类问题。

<小时/>

如果感觉像上面的场景中那样重载拒绝是一种黑客行为(确实如此),那么您可以编写自己的迭代方法,该方法使用解析值约定来告诉迭代器何时停止:

自定义迭代

Promise.eachStop = function(array, fn) {
var index = 0;

return new Promise(function(resolve, reject) {

function next() {
if (index < array.length) {
// chain next promise
fn(array[index], index, array.length).then(function(result) {
if (typeof result === "object" && result.stopIteration === true) {
// stopped after processing index item
resolve(index);
} else {
// do next iteration
++index;
next();
}
}, reject);
} else {
// finished iteration without stopping
resolve(null);
}
}

// start the iteration
next();
});
}

这里,如果迭代器解析的值是一个对象,则该对象具有属性 stopIteration: true ,那么迭代器将停止。

如果任何地方出现错误,最终的 Promise 将被拒绝,并以 null 的值解析。如果迭代器完成并且从未停止,或者带有一个数字,该数字是迭代停止的索引。

你可以像这样使用它:

Promise.eachStop(data, function(item, index, length) {
return checkIfItemExists(item).then(function(exists) {
if (!exists) {
return addItemToDb(item).then(function() {
// return special coded object that has stopIteration: true
// to tell the iteration engine to stop
return {stopIteration: true};
});
}
})
}).then(function(result) {
if (result === null) {
// finished the iteration, but nothing was added to the DB
} else {
// added result item to the database and then stopped further processing
}
}, function(err) {
// error
});
<小时/>

告诉迭代器是否跳过其工作的标志变量

在进一步考虑这个问题时,我想出了另一种方法来做到这一点,即允许 Promise.each()迭代运行至完成,但设置一个更高范围的变量来告诉迭代器何时应该跳过其工作:

var data = [...];
// set property to indicate whether we're done or not
data.done = false;

Promise.each(data, function(item, index, length) {
if (!data.done) {
return checkIfItemExists(item).then(function(exists) {
if (!exists) {
return addItemToDb(item).then(function() {
data.done = true;
});
}
})
}
}).then(function() {
// finished
}, function(err) {
// error
});

关于bluebird - 中断 Bluebird .each() 进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36937532/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com