简化承诺链

时间:2016-06-17 13:05:00

标签: javascript ecmascript-6

我试图通过让函数处理一系列函数来尽可能地简化Promise链。它们需要按顺序排列,但我给它们正确语法的方法并不奏效,而且我确信有更好的方法可以做到这一点。链中的每个函数都调用数据库,并在返回时需要触发下一个函数。

// Run each in order.
var Chain = function(chain, cb){
    chain.forEach(function(i){  i = function(r){return new Promise(i)};   });
    chain.reduce(function(cur, next) { {cur.then(next)} }, Promise.resolve()).then(function() { cb() });
}
Chain([

    r=>{ 
        UserData('elle',  i=>{ 
            console.log(i);
            r(i)
        }) 
    },
    r=>{ 
        UserData('tyler', {age:"22"}, i=>{ 
            console.log(i);
            r(i);
        }) 
    },
    r=>{ 
        UserData('nerd',  i=>{ 
            console.log(i);
            r(i) 
        }) 
    },
    r=>{ 
        UserData('jeax',  i=>{ 
            console.log(i);
            r(i) 
        }) 
    }

], function(){

    console.log("Done.");

});

以下示例运用我的需要,只是不使用我想要的链功能,每个项目的简单性。

var PChain = function(cb){
    // Convert each item.
    return function(){ return new Promise(r=>{cb(r)}) };
}
// The items.
var chain = [
    PChain(r=>{ 
        UserData('elle',  i=>{ 
            console.log(i);r(i)
        }) 
    }),
    PChain(r=>{ 
        UserData('tyler', {age:"22"}, i=>{ 
            console.log(i);r(i);
        }) 
    }),
    PChain(r=>{ 
        UserData('nerd',  
            i=>{ console.log(i);r(i) 
        }) 
    }),
    PChain(r=>{ 
        UserData('jeax',  
            i=>{ console.log(i);r(i) 
        }) 
    })
];
chain.reduce(function(cur, next) { return cur.then(next) }, Promise.resolve()).then(function() {
    //all executed
    console.log("Done.");
});

2 个答案:

答案 0 :(得分:2)

你的错误在于Chain功能:

chain.forEach(function(i){  i = function(r){return new Promise(i)};   });
chain.reduce(function(cur, next) { {cur.then(next)} }, Promise.resolve()).then(function() { cb() });

具体而言,在i内分配forEach绝对没有任何意义。你真正想要的是使用map

chain.map(function(exec){ return function(r){ return new Promise(exec)}; }).reduce(…);

其中map返回一个可以减少的函数数组。

无论如何,您实际应该做的是promisify UserData功能:

function user(name, options) {
    return new Promise((resolve, reject) => {
        if (options)
            UserData(name, options, resolve);
        else
            UserData(name, resolve);
    });
}

您甚至不需要连锁店,但可以简单地写

user('elle').then(i => { 
    console.log(i);
    return user('tyler', {age:"22"});
}).then(i => { 
    console.log(i);
    return user('nerd');
}).then(i => {
    console.log(i);
    return user('jeax');
}).then(i => {
    console.log(i);
}).then(function() {
   //all executed
   console.log("Done.");
});

如果你有一个动态大小的用户名数组,你仍然可以使用reduce,但你不应该使用一组函数。

答案 1 :(得分:1)

您应该使用Promise.all(iterable)

Promise.all([r1, r2, r3]).then(function(values) { 
  // Do something
});

<强>更新

要尊重特定订单,您应该check this answer。遗憾的是,没有ES6方法可以原生这样做。

最常用的JS承诺排队系统(其中,by Angular)之一是Kris Kowal的Q而且它recommend something similar,所以这与你写的不太一样。

注意

在您的代码中,您似乎正在尝试实现某种批量请求。你必须知道在JS中真正需要一个有序的Promises链是非常缺乏的。

  1. 如果您将其用于流程(例如文件内容操作),最好使用pipes
  2. 如果您将其用于批处理/过滤的API请求:
    • 如果您控制API:更改您的API以管理批量/过滤的请求
    • 如果您不控制它:创建一个管理它的中间件应用程序