减少数组链接承诺
此设计模式对于从元素列表生成一系列异步操作非常有用。
有两种变体:
- 然后减少,只要连锁经历成功,就会建立一个持续的链条。
- 捕获减少,只要链条出现错误,就会建立一个持续的链条。
****然后减少
这种模式的变体构建了一个 .then() 链,可能用于链接动画或制作一系列依赖的 HTTP 请求。
[1, 3, 5, 7, 9].reduce((seq, n) => {
return seq.then(() => {
console.log(n);
return new Promise(res => setTimeout(res, 1000));
});
}, Promise.resolve()).then(
() => console.log('done'),
(e) => console.log(e)
);
// will log 1, 3, 5, 7, 9, 'done' in 1s intervals
说明:
- 我们在源数组上调用
.reduce(),并提供Promise.resolve()作为初始值。 - 减少的每个元素都会将
.then()添加到初始值。 reduce()的产品将是Promise.resolve()。然后(…)。然后(…)。- 我们在 reduce 之后手动附加
.then(successHandler, errorHandler),以便在前面的所有步骤都已解决后执行successHandler。如果任何步骤失败,则errorHandler将执行。
注意:then 减少是 Promise.all() 的顺序对应。
****捕获减少
这种模式的变体构建了一个 .catch() 链,可用于为一些镜像资源顺序探测一组 Web 服务器,直到找到工作服务器。
var working_resource = 5; // one of the values from the source array
[1, 3, 5, 7, 9].reduce((seq, n) => {
return seq.catch(() => {
console.log(n);
if(n === working_resource) { // 5 is working
return new Promise((resolve, reject) => setTimeout(() => resolve(n), 1000));
} else { // all other values are not working
return new Promise((resolve, reject) => setTimeout(reject, 1000));
}
});
}, Promise.reject()).then(
(n) => console.log('success at: ' + n),
() => console.log('total failure')
);
// will log 1, 3, 5, 'success at 5' at 1s intervals
说明:
- 我们在源阵列上调用
.reduce(),并提供Promise.reject()作为初始值。 - 每个元素减少将一个添加
.catch()到初始值。 reduce()的产品将是Promise.reject().catch(…).catch(...)。- 我们在 reduce 之后手动附加
.then(successHandler, errorHandler),以便在前面的任何步骤解决后执行successHandler。如果所有步骤都失败了,那么errorHandler将会执行。
注意:catch 减少是 Promise.any() 的顺序对应(在 bluebird.js 中实现,但目前不在本机 ECMAScript 中)。