1

私はこのような約束の機能を使用しています:forEachのようなjavascriptの関数関数でpromise関数を使用する方法は?

// WORK 
let res = {approveList: [], rejectList: [], errorId: rv.errorId, errorDesc: rv.errorDesc}; 
for (let i = 0; i < rv.copyDetailList.length; i ++) { 
    const item = rv.copyDetailList[i]; 
    const v = await convertCommonInfo(item); 
    if (!item.errorId) { 
     res.approveList.push(v); 
    } else { 
     res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg})); 
    } 
} 

これはうまく動作しますが、私は、いくつかの機能の機能を使用しようとする場合、私は私が

// WORK, But with two traversal 
const dataList = await promise.all(rv.copyDetailList.map((item) => convertCommonInfo(item))); 

const res = dataList.reduce((obj, v, i) => { 
    const item = rv.copyDetailList[i]; 
    if (!item.errorId) { 
     obj.approveList.push(v); 
    } else { 
     obj.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg})); 
    } 

    return obj; 
}, {approveList: [], rejectList: [], errorId: rv.errorId, errorDesc: rv.errorDesc}); 

を減らし、その後mapを使用する必要があることを見つけますforEach機能が動作しないことを見つける:これは動作しません

// NOT WORK, not wait async function 
rv.copyDetailList.forEach(async function(item) { 
    const v = await convertCommonInfo(item); 
    if (!item.errorId) { 
     res.approveList.push(v); 
    } else { 
     res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg})); 
    } 
}); 

、それだけで初期化値を返します。 実際にこのパズル私、正弦私はawait機能、なぜ動作しないのですか?

がでも私はreduce機能を使用したい:

error TS2345: Argument of type '(prev: { approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }, item: Resp...' is not assignable to parameter of type '(previousValue: { approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }, c...'. 
Type 'Promise<void>' is not assignable to type '{ approveList: any[]; rejectList: any[]; errorId: string; errorDesc: string; }'. 
Property 'approveList' is missing in type 'Promise<void>'. 

だから私は二つのことを知りたい:

// NOT WORK, Typescirpt can not compile 
rv.copyDetailList.reduce(async function(prev, item) { 
    const v = await convertCommonInfo(item); 
    if (!item.errorId) { 
     prev.approveList.push(v); 
    } else { 
     prev.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg})); 
    } 
}, res); 

しかし、私はTypescriptを使用しておりますのでを、私はこのようなエラーが発生しました

  1. なぜforEach awaitできません仕事?
  2. reduceでpromise関数を使用できますか?
+0

の可能重複[使用非同期/ foreachループで待つ](http://stackoverflow.com/q/37576685/1048572) ( 'reduce'と同じです) – Bergi

答えて

1

あなたはおそらくこれに近づいています。

// assumes curried times and add functions 
let tranformData = _.compose(square, times(2), add(3)); 

let foo = fetchNumberAsync() // returns a promise of 3 
    .then(transformData) 
    .catch(err => doSomethingWithError(err)); 

foo.then(n => console.log(n)); // prints 144 to the console ((3 + 3) * 2) ** 2 

が選択肢と比較:

// clear but wasteful 
let foo = fetchNumberAsync() 
    .then(n => n + 3) 
    .then(n => n * 2) 
    .then(n => n ** 2) 

または

// performant but opaque 
let foo = fetchNumberAsync().then(n => ((n + 3) * 2) ** 2) 
一般的に、あなたは約束の .thenハンドラにその構成機能をすべての変換を組み合わせて渡すこと composeを使用したいです

compose(特にmemoize)を使用すると、中道に適しています。

1

なぜそれぞれの待ち時間が働かないのですか? forEachに非同期関数を提供しますが、forEach関数の実装内では待機しません。

Array.prototype.forEach = function (func) { 
    for (let item of this) { 
     func(item); // Note here, there is no "await" in front of it 
    } 
} 

私は削減に約束の機能を使用することができます。私はforEachのはそのようですね? いいえ、あなたは上記と同じ理由ではありません。あなたのコードを滑らかにする

「コ」を経由して別の方法は、以下のようなものです:

let ret = await rv.copyDetailList.map(co(function * (item) { 
    const v = yield convertCommonInfo(item); 
    if (!item.errorId) { 
     res.approveList.push(v); 
    } else { 
     res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg})); 
    } 
})); 
1

あなたの究極の目標は、各反復が同時に実行される単一トラバーサルを達成することである場合、その利用可能なさまざまなライブラリがありますをそれぞれ "非同期で"のように、あなたが探しているように聞こえるようにします。

このようなライブラリの1つはasync-parallelです。これは、Parallel.eachのasync/awaitでうまく動作するイテレータを提供します。あなたのコードは次のようになります。このライブラリを使用して

...

let res = {approveList: [], rejectList: [], errorId: rv.errorId, errorDesc: rv.errorDesc}; 
await Parallel.each(rv.copyDetailList, async (item) => { 
    var v = await convertCommonInfo(item); 
    if (!item.errorId) 
     res.approveList.push(v); 
    else 
     res.rejectList.push(merge(v, {errorId: item.errorId, errorDesc: item.errorMsg})); 
}); 
関連する問題