2017-10-23 5 views
1

私は現在、javascriptで非同期呼び出しのペアの配列を生成しようとしていますが、正しい順序で取得できないようです。約束のあるデータセットを生成

generateDataPoints: function (iterable, source, arg) { 
    let pairs = [] 
    let prevTime = 0 
    for (let index in iterable) { 
    let event = iterable[index] 
    getTime(event.valueOf()).then(function (time) { 
     query(source[arg], event.valueOf()).then(function(val) { 
     if (time !== prevTime) { 
      prevTime = time 
      pairs.push([time, val]) 
      console.log(pairs) // This works as expected but only happens after the program returns 
     } else { 
      Promise.resolve() 
     } 
     }) 
    }) 
    } 
    return Promise.resolve(pairs) 
} 

問題は、私が戻った後に "pairs.push .."コマンドが発生することです。私は正確に何がうまくいかないのか、どのようにこのプロセスを同期させることができるのか理解できません。どんな助けもありがとうございます。

+0

だから...あなたは確かにあなたのコードに約束を導入しましたが、あなたがそれをしたことで何もしなかったという約束は返されません作業が完了するまで解決してください。 –

+0

@KevinB Hm、私は新しいPromiseでforループをラップしようとしましたが、 "resolve(pairs)"を返しました。それでもどちらもうまくいかなかった – WhosSu

+0

あなたは 'Promise.all'を探しています。ループを使用して、個々の結果ごとに1つの約束事を作成します。 – Bergi

答えて

0

同期コード(forループなど)と非同期コードを混在させています。

function generateDataPoints(iterable, source, arg) { 
    let prevTime = 0 
    [...iterable].reduce((promiseChain, event) => { 
    let pairs; 
    return promiseChain 
     .then(p => { 
     pairs = p; 
     return Promise.all([ 
      getTime(event.valueOf()), 
      query(source[arg], event.valueOf()) 
     ]) 
     }) 
     .then(([time, val]) => { 
     if (time !== prevTime) { 
      prevTime = time 
      return pairs.concat([[time, val]]); 
     } else { 
      return pairs; 
     } 
     }); 
    }) 
    }, Promise.resolve([])); 
} 

これは、最終的にすべてのペアが含まれていますシーケンシャル約束チェーンへiterableを削減します。このような何かを試してみてください。ご使用の環境がそれを可能にしている場合

、あなたも非同期機能にいくつかの変更を使用して機能を変換することができます:

generateDataPoints: async function (iterable, source, arg) { 
    let pairs = [] 
    let prevTime = 0 
    for (let index in iterable) { 
    let event = iterable[index] 
    const [time, val] = await Promise.all([ 
     getTime(event.valueOf()), 
     query(source[arg], event.valueOf()) 
    ]); 
    if (time !== prevTime) { 
     prevTime = time 
     pairs.push([time, val]) 
    } 
    } 
    return pairs; 
} 

編集

を詳しく見では、それはしていませんこれらの約束を逐次化する必要があるように見えます。

function generateDataPoints(iterable, source, arg) { 
    Promise.all(
    [...iterable].map(event => Promise.all([ 
     getTime(event.valueOf()), 
     query(source[arg], event.valueOf()) 
    ]) 
).then(pairs => { 
    let prevTime = 0 
    return pairs.filter(([time, val]) => { 
     if (time !== prevTime) { 
     prevTime = time; 
     return true; 
     } else { 
     return false; 
     } 
    }); 
    }); 
} 
+0

あなたはタグに従ってBluebirdも使用しています。つまり、物事をさらに簡単にする 'Promise.map'のようなグッズがあります。 – Jacob

+0

私は現在あなたが書いた3番目のことを実装しました。ここに問題があります。私はどこか別の場所で呼び出されたgenerateDataPointsを持って、関数xを呼び出すことができます。マッピングが行われた後、Xはペアのリストを取得しますが、フィルタ処理は開始されていません。どうしてこれなの? – WhosSu

+0

これは現在のように見えます。https://pastebin.com/shukspGj – WhosSu