JavaScript 将数组简化为链接的承诺

示例

此设计模式对于从元素列表生成一系列异步操作很有用。

有两种变体:

  • “那么”的减少,它建立了一条链,只要该链成功就可以持续下去。

  • “捕获”减少量,它构建了一条链,只要链遇到错误,该链就会持续。

“然后”减少

这种模式的变体建立了一个链,可以用于链接动画或发出一系列相关的HTTP请求。.then()

[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)
);
// 将以1s的间隔记录1,3,5,7,9,9,完成

说明:

  1. 我们调用一个源数组,并提供一个初始值。.reduce()Promise.resolve()

  2. 减少的每个元素都会在初始值上加上a 。.then()

  3. reduce()的产品将是.then(...)。then(...)。Promise.resolve()

  4. 我们在reduce后面手动添加一个,以在所有前面的步骤都解决后执行。如果任何步骤失败,则将执行。.then(successHandler, errorHandler)successHandlererrorHandler

注意:“ then”减少量是的顺序对应物。Promise.all()

“渔获”减少

该模式的这种变体构建了一条链,可以用于顺序探测一组镜像资源的一组Web服务器,直到找到工作的服务器为止。.catch()

var working_resource = 5; // 源数组中的值之一
[1, 3, 5, 7, 9].reduce((seq, n) => {
    return seq.catch(() => {
        console.log(n);
        if(n === working_resource) { // 5正在工作
            return new Promise((resolve, reject) => setTimeout(() => resolve(n), 1000));
        } else { // 所有其他值都不起作用
            return new Promise((resolve, reject) => setTimeout(reject, 1000));
        }
    });
}, Promise.reject()).then(
    (n) => console.log('success at: ' + n),
    () => console.log('total failure')
);
// 将以1s的间隔记录1,3,5,'成功于5'

说明:

  1. 我们调用一个源数组,并提供一个初始值。.reduce()Promise.reject()

  2. 减少的每个元素都会在初始值上加上a 。.catch()

  3. reduce()的产品将会。Promise.reject().catch(...).catch(...)

  4. 在reduce之后,我们会手动追加,以解决前面的任何步骤。如果所有步骤均失败,则将执行。.then(successHandler, errorHandler)successHandlererrorHandler

注意:“ catch”减少是(在,但当前不在本机ECMAScript中实现的)顺序对应项。Promise.any()bluebird.js