web-dev-qa-db-ja.com

この非同期のforeachループをpromiseで機能させるにはどうすればよいですか?

私はすでにPromiseをいじっていますが、Promiseは初めてなので、適切に実行する方法がわかりません。現時点では、非同期になるまで待機しないため、Promiseに意味はありません$.get完了します。

基本的に、各foreach反復には独自の$.get関数を使用して、すべてを完成させてから、「... gets albumart」がある部分に進む必要がありますconsole.log

$.get(id,function(data) {
    //(there's some code here)
    var getZippyUrls = new Promise(function(resolve) {
            zippyarray.forEach(function(zippy) {
            //(more code)
            $.get(zippy.full, function(data) {
                //^This is the foreach of $.gets
               //(code's here)
            });  
           resolve(zippyarray);
        });
    });

    //This is my failed Promise ->
    getZippyUrls.then(function(response) {
        console.log("WE'RE OUT " + response.length);
        response.foreach(function(d) {
            console.log("Promise"+d.media);
        });
        console.log('eyyyyyy');
    });

    console.log("...gets albumart");
    //Now after the previous stuff is done, move on
14
Fabis

同期コードでは、行が終了すると継続が実行されます;

Promiseでは、継続は.thenを介して実行されます。あなたはpromiseコンストラクターを使用していて、それをすぐに解決しました。タスクをまったく待ちませんでした。私は自分の仕事をタスクにマップし、それをそれらとチェーンするか、または順番に待ちます。

//I'm assuming
zippyarray; // array of Zippy objects

var tasks = zippyarray.map(function(zippy,i){
    return function(){ // return a task on that zippy;
       // basic logic here
       return $.get({
            // ajax request
       }).then(function(data){
            // process data like in your code
            // possibly store later for later use too
            return process(data); // return the processed data;
       });
    }
});

これで、すべてを順番に実行できます。

 var p = tasks[0](); // start the first one
 for(var i = 1; i < tasks.length; i++) p = p.then(tasks[i]);
 p.then(function(result){
       // all available here
 });

以上、連続的に:

$.when.apply(tasks.forEach(function(t){ return t(); })).then(function(results){
     // all done
})
19

私はこれが古い質問であることを知っていますが、最近状況が少し変わっています。

外部ライブラリの使用に問題がない場合、Bluebirdpromiseライブラリは、これに対してかなり良い実装を持っています: Promise.each

例えば。

function helperFunc(zippyarray) {
  return Promise.each(zippyarray, zippy => {
    return someOperationThatReturnAPromise(zippy)
      .then((singleResult) => {
        // do something with the operation result if needed
      })
  }).then((originalArray) => {
    // this happens only after the whole array is processed
    // (result is the original array here)
    return Promise.resolve(originalArray)
  })
}
10
MJV

複数のget-Requestを追跡するには、次のように使用します。

var cnt = requestCnt;

function finished(){
    if(--cnt)return;
    // Your code here
}

for(var i = 0; i < requestCnt; ++i){
    $.get('something.htm', {data:data}, function(data){
        finished();
    });
}

リクエストが応答を受け取ったときは、常にfinished関数を呼び出します。完成した関数は、すべてが完了するとその仕事をします。

0
Fuzzyma

今日、順次実行する必要がある場合は、async/await

//I'm assuming I'm inside an `async` function
zippyarray; // array of Zippy objects

for(const task of zippyArray) {
  const result = await $.get({ ... });
  // do stuff with result
}
0