减少数组链接承诺
此设计模式对于从元素列表生成一系列异步操作非常有用。
有两种变体:
- 然后减少,只要连锁经历成功,就会建立一个持续的链条。
- 捕获减少,只要链条出现错误,就会建立一个持续的链条。
****然后减少
这种模式的变体构建了一个 .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 中)。