给定一个函数, fn
,它返回一个promise,以及一个任意长度的数据数组(例如 data = ['apple', 'orange', 'banana', ...]
),如何依次对数组的每个元素进行函数调用,这样如果_1215603解析,整个链完成并停止调用 fn
,但如果 fn(data[i])
拒绝,下一次调用 fn(data[i + 1])
会执行吗?
这是一个代码示例:
// this could be any function which takes input and returns a promise
// one example might be fetch()
const fn = datum =>
new Promise((resolve, reject) => {
console.log(`trying ${datum}`);
if (Math.random() < 0.25) {
resolve(datum);
} else {
reject();
}
});
const foundResult = result => {
// result here should be the first value that resolved from fn(), and it
// should only be called until the first resolve()
console.log(`result = ${result}`);
};
// this data can be purely arbitrary length
const data = ['apple', 'orange', 'banana', 'pineapple', 'pear', 'plum'];
// this is the behavior I'd like to model, only for dynamic data
fn('apple').then(foundResult)
.catch(() => {
fn('orange').then(foundResult)
.catch(() => {
fn('banana').then(foundResult)
.catch(() => {
/* ... and so on, and so on ... */
});
});
});
我觉得可能还有's an elegant solution to this pattern that I'失踪了 . 这种行为与 Array.some()
非常相似,但是我试图摆弄那个空洞 .
EDIT: I switched from numeric data to string to stress that the solution needs to not be reliant on the data being numeric.
EDIT #2: Just to clarify further, fn could be any function that accepts input and returns a promise. The fn implementation above was just to give a complete example. In reality, fn could actually be something like an API request, a database query, etc.
5 回答
你可以使用
async/await
和一个循环:fn
可以返回Promise(等待)或只返回一个值(返回)你的
data
可能是一个无限iterable
序列(生成器)在我看来,它也易于阅读和理解意图 .
如果序列失败,这是输出:
异步的支持在es2017中是原生的,但可以用babel或typescript转换为es3 / es5
您可以使用Array.reduce来获取所需的数据 .
基本上它会在结果通过后将结果传递给结束 . 如果
fn
失败,它会将未定义的值承诺传递给下一个链以触发fn
.编写如下搜索功能:
你可以编写一个非常简单的递归函数,它将在第一个解析时停止并在catch上递归 .
如果找到匹配项并且不关心
data
的长度,除非您超过递归中的堆栈大小,否则这样做的好处是可以在第一次匹配时停止而不调用所有值 . 当然,当所有承诺都拒绝做某事时,修改边缘情况的动作会很容易 .找到结果:
并没有找到:
你想要做的就是这样做我猜(它不是严格等同的,见下面的储备):
使用Promise.race:
但是我不确定这是你想要实现的:例如在你的代码片段中你没有返回
catch
处理程序中的任何内容,这意味着foundResult
很可能是副作用 . 此外,在阅读您的代码片段时,您将捕获可以从foundResult
内部而不是从fn
函数中引发的错误 .作为一个经验法则,我总是试图通过已知的"type"履行我的承诺,或者拒绝错误 . 它's not clear in your example that the promise you are generating will be settled with any value, whether it'是
rejectionValue
或fulfillmentValue
.也许如果你提供一个用例,我可以帮助你一点 .