javascript - 实现 Promise.series 作为 Promise.all 的替代品

标签 javascript node.js ecmascript-6 es6-promise

我看到了 Promise.all 的这个示例实现 - 它并行运行所有 promise - Implementing Promise.all

请注意,我正在寻找的功能类似于 Bluebird 的 Promise.mapSeries http://bluebirdjs.com/docs/api/mapseries.html

我正在尝试创建 Promise.series,我有这个似乎按预期工作(它实际上是完全错误的,不要使用它,查看答案):

Promise.series = function series(promises){

    return new Promise(function(resolve,reject){

    const ret = Promise.resolve(null);
    const results = [];

    promises.forEach(function(p,i){
         ret.then(function(){
            return p.then(function(val){
               results[i] = val;
            });
         });
    });

    ret.then(function(){
         resolve(results);
    },
     function(e){
        reject(e);
     });

    });

}


Promise.series([
    new Promise(function(resolve){
            resolve('a');
    }),
    new Promise(function(resolve){
            resolve('b');
    })
    ]).then(function(val){
        console.log(val);
    }).catch(function(e){
        console.error(e.stack);
    });

但是,此实现的一个潜在问题是,如果我拒绝一个 promise,它似乎并没有捕捉到它:

 Promise.series([
    new Promise(function(resolve, reject){
            reject('a');   // << we reject here
    }),
    new Promise(function(resolve){
            resolve('b');
    })
    ]).then(function(val){
        console.log(val);
    }).catch(function(e){
        console.error(e.stack);
    });

有谁知道为什么错误没有被捕获,是否有办法用 Promises 解决这个问题?

根据评论,我做了这个更改:

Promise.series = function series(promises){

    return new Promise(function(resolve,reject){

    const ret = Promise.resolve(null);
    const results = [];

    promises.forEach(function(p,i){
         ret.then(function(){
            return p.then(function(val){
               results[i] = val;
            },
            function(r){
                console.log('rejected');
                reject(r);   // << we handle rejected promises here
            });
         });
    });

    ret.then(function(){
         resolve(results);
    },
     function(e){
        reject(e);
     });

    });

}

但这仍然没有按预期工作......

最佳答案

forEach 循环中 then 返回的 promise 不处理潜在的错误。

正如@slezica 在评论中指出的那样,尝试使用 reduce 而不是 forEach,这会将所有 promise 链接在一起。

Promise.series = function series(promises) {
    const ret = Promise.resolve(null);
    const results = [];

    return promises.reduce(function(result, promise, index) {
         return result.then(function() {
            return promise.then(function(val) {
               results[index] = val;
            });
         });
    }, ret).then(function() {
        return results;
    });
}

请记住, promise 此时已经“运行”。如果你真的想串行运行你的 promise ,你应该调整你的功能并传入一个返回 promise 的函数数组。像这样:

Promise.series = function series(providers) {
    const ret = Promise.resolve(null);
    const results = [];

    return providers.reduce(function(result, provider, index) {
         return result.then(function() {
            return provider().then(function(val) {
               results[index] = val;
            });
         });
    }, ret).then(function() {
        return results;
    });
}

关于javascript - 实现 Promise.series 作为 Promise.all 的替代品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37578795/

相关文章:

node.js - 什么是 TTY 以及如何在 Ubuntu 上启用它?

node.js - 如何在 Angular 中谨慎使用 localStorage

android - 加密 Node Js

javascript - 通过操作 DOM w 更改内容。 Javascript 与创建新的 HTML/CSS 页面 : which is more efficient?

javascript - React - 如何在功能组件上打开显示更多?

javascript - 我不明白 jQuery.data() 方法

javascript - Vuex createNamespacedHelpers 不起作用

javascript - 提交按钮不起作用

带有 ES6 类的动态 getter / setter

node.js - NodeJS 中的多个 await 调用错误处理