web-dev-qa-db-ja.com

ES6の約束-async.eachのようなもの?

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];

ここで、並列ではなく直列で実行したいので、「非同期」NPMを使用すると簡単です。

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

私の質問は次のとおりです。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();
}
26
Shlomi Sasson

短い答えが好きな人のために:

[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());
47
jib

データの配列で非同期関数を呼び出し、並列ではなく順次呼び出したいとします。

async.eachSeries()のインターフェースは次のとおりです。

_eachSeries(arr, iterator, [callback])
_

これをpromiseでシミュレートする方法は次のとおりです。

_// 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());
}
_

これは、iteratorFnが処理するアイテムを引数として取り、それがpromiseを返すことを前提としています。

以下に使用例を示します(これは、約束されたfs.readFileAsync()があることを前提としています)、完了時にpromiseを返すspeak()という関数があるとします。

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

これにより、Promiseインフラストラクチャがすべてのシーケンスを行います。


手動でシーケンスすることも可能です(理由はわかりません)。

_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();
    });
}
_

または、promiseを手動でチェーンする単純なバージョン:

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

    function next() {
        if (index < arr.length) {
            return iteratorFn(arr[index++]).then(next);
        }
    }
    return Promise.resolve().then(next);
}
_

手動バージョンの1つがiteratorFn()を_try/catch_で囲んで、安全であることを確認する必要があることに注意してください(例外を拒否に変換します)。 .then()は自動的に安全にスローされるため、.then()は既に例外をキャッチしているため、他のスキームは手動で例外をキャッチする必要がありません。

14
jfriend00

@ jibによって提供される回答 ...の拡張として、次のようにアイテムの配列を非同期関数にマップすることもできます。

[item1, item2]
    .map(item => async (prev_result) => await something_async(item))
    .reduce((p, f) => p.then(f), Promise.resolve())
    .then(() => console.log('all done'));

prev_resultsomething_asyncの前回の評価で返される値になることに注意してください。これは、async.eachSeriesasync.waterfallのハイブリッドとほぼ同じです。

1
Blake Regalia

// nodejsのバージョンが低いシステムでこれをアップロードする(Azure:/)最短ではないが、私が考えることができる最も優れたもの

たとえば、「functionWithPromise」がいくつかのプロミスを返し、いくつかのアイテムを期待しているとしましょう。

functionWithPromise(item);

promisesArray =[];

//syncornized
itemsArray.forEach(function (item){
   promisesArray.Push(functionWithPromise(item));
});

Promise.all(promisesArray).then(function (values){
//profit
});
0
adi ben

thenコールバックで戻ることで連鎖できます。例えば:

new Promise(function(resolve, reject){ 
  resolve(1)
}).then(function(v){
  console.log(v);
  return v + 1;
}).then(function(v){
  console.log(v)
});

印刷されます:

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);
});

印刷:

1
2

0
Kit Sunde