ES6 Promises - 像async.each这样的东西?

Shl*_*son 26 javascript asynchronous ecmascript-6 es6-promise

试图弄清楚如何找到与async.eachSeries完全相同的功能,我需要一个按顺序运行的异步动作列表(不是并行)但是找不到在原生ES6中执行它的方法,任何人都可以建议,请?

ps考虑了发电机/产量,但还没有经验,所以我没有意识到它究竟能帮助我.

编辑1

根据请求,这是一个例子:

假设这段代码:

let model1 = new MongooseModel({prop1: "a", prop2: "b"});
let model2 = new MongooseModel({prop1: "c", prop2: "d"});

let arr = [model1 , model2];
Run Code Online (Sandbox Code Playgroud)

现在,我想在一系列中运行它,而不是并行,所以使用"异步"NPM很容易:

async.eachSeries(arr, (model, next)=>{
    model.save.then(next).catch(next);
}, err=>{
    if(err) return reject(error);
    resolve();
})
Run Code Online (Sandbox Code Playgroud)

我的问题是:使用ES6,我可以原生使用吗?没有NPM'异步'包?

编辑2

使用async/await可以轻松完成:

let model1 = new MongooseModel({prop1: "a", prop2: "b"});
let model2 = new MongooseModel({prop1: "c", prop2: "d"});    

let arr = [model1 , model2];

for(let model of arr){
    await model.save();
}
Run Code Online (Sandbox Code Playgroud)

jib*_*jib 47

对于那些喜欢简短答案的人:

[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());
Run Code Online (Sandbox Code Playgroud)

  • 我只是有一个小小的高潮 (10认同)
  • 第二个参数是缩减的[初始值](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce).例如,这个特定的例子相当于`Promise.resolve().然后(func1).then(func2)`. (5认同)
  • 你是魔术师.正是我需要的. (2认同)

jfr*_*d00 14

假设您想在数据数组上调用一些异步函数,并且希望它们按顺序调用,而不是并行调用.

接口async.eachSeries()是这样的:

eachSeries(arr, iterator, [callback])
Run Code Online (Sandbox Code Playgroud)

以下是使用promises模拟的方法:

// define helper function that works kind of like async.eachSeries
function eachSeries(arr, iteratorFn) {
    return arr.reduce(function(p, item) {
        return p.then(function() {
            return iteratorFn(item);
        });
    }, Promise.resolve());
}
Run Code Online (Sandbox Code Playgroud)

这假设iteratorFn将项目作为参数处理并返回一个promise.

这是一个用法示例(假设您有一个promisified fs.readFileAsync())并且有一个调用的函数speak()在完成时返回一个promise:

 var files = ["hello.dat", "goodbye.dat", "genericgreeting.dat"];
 eachSeries(files, function(file) {
     return fs.readFileAsync(file).then(function(data) {
         return speak(data);
     });
 });
Run Code Online (Sandbox Code Playgroud)

这使得承诺基础设施可以为您排序.


你也可以手动排序(虽然我不知道为什么):

function eachSeries(arr, iteratorFn) {
    return new Promise(resolve, reject) {
        var index = 0;

        function next() {
            if (index < arr.length) {
                try {
                    iteratorFn(arr[index++]).then(next, reject);
                } catch(e) {
                    reject(e);
                }
            } else {
                resolve();
            }
        }
        // kick off first iteration
        next();
    });
}
Run Code Online (Sandbox Code Playgroud)

或者,一个更简单的版本,手动将承诺链接在一起:

function eachSeries(arr, iteratorFn) {
    var index = 0;

    function next() {
        if (index < arr.length) {
            return iteratorFn(arr[index++]).then(next);
        }
    }
    return Promise.resolve().then(next);
}
Run Code Online (Sandbox Code Playgroud)

请注意其中一个手动版本必须iteratorFn()包含try/catch在内以确保它是安全的(将异常转换为拒绝). .then()自动抛出安全,因此其他方案不必手动捕获异常,因为.then()已经为您捕获它们.


Kit*_*nde 0

您可以通过在回调中返回来链接then。例如:

new Promise(function(resolve, reject){ 
  resolve(1)
}).then(function(v){
  console.log(v);
  return v + 1;
}).then(function(v){
  console.log(v)
});
Run Code Online (Sandbox Code Playgroud)

将打印:

1
2

这在异步解决 Promise 时当然有效:

new Promise(function(resolve, reject){
  setTimeout(function(){
    resolve(1);
  }, 1000)
}).then(function(result){
   return new Promise(function(resolve, reject){
     setTimeout(function(){
       console.log(result);
       resolve(result + 1);
     }, 1000)
   });
}).then(function(results){
  console.log(results);
});
Run Code Online (Sandbox Code Playgroud)

印刷:

1
2