2016-04-12 2 views
0

配列からajax呼び出しのループを作成し、すべての呼び出しが正常に受信されたときに印刷する各データ結果を保存しようとしています。ajaxの終了ループは、呼び出しの1つからエラーを破る代わりに配列を呼び出します

問題は、エラーを返すajax呼び出しがあると、プロセス全体が中断され、コールバックが実行されないということです。 (listWithErrorResultを試してみてください)

ループを壊さずに何かをプッシュするには?

JSFIDDLE

var list = ['UQ13nr6urIo', 'hxa_Z0eZ83E', 'ulHB2mNlovg']; 
 
var listWithErrorResult = ['UQ13nr6urIo', 'hxa_Z0eZ83E', 'IWEHeIdBkc4']; 
 

 
var callback = function() { 
 
    console.log("done"); 
 
    console.log(tracks); 
 
}; 
 

 
var requests = [], tracks = []; 
 

 
    for(i = 0; i < list.length; i++) { 
 
    requests.push($.ajax({ 
 
     url: 'http://www.youtubeinmp3.com/fetch/?format=JSON&video=https://www.youtube.com/watch?v='+list[i], 
 
     dataType: "json", 
 
     success: function(data) { 
 
     console.log('suc'); 
 
     tracks.push(data); 
 
     },error: function() { 
 
\t  console.log('err'); 
 
\t  tracks.push('err'); 
 
\t  } 
 
    })); 
 
    } 
 

 
$.when.apply(undefined, requests).then(function(results){callback()});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

答えて

1

あなたは自分のAJAXコールに.then()ハンドルを取り付け、すべてのAJAX呼び出しは解決ではなく、拒否を確認することができます。これは、すべてあなたのAJAX呼び出しを含めることが保証されて最後にあなたに結果の配列を取得します:

あなたはまた、私はそれがすべての約束は終了していますすることができます書いた $.settle()のバージョンを使用することができます
var callback = function(/* tracks are passed here as arguments */) { 
    console.log("done"); 
    var tracks = Array.prototype.slice.call(arguments); 
    console.log(tracks); 
}; 

var requests = []; 

    for(var i = 0; i < list.length; i++) { 
    requests.push($.ajax({ 
     url: 'http://www.youtubeinmp3.com/fetch/?format=JSON&video=https://www.youtube.com/watch?v='+list[i], 
     dataType: "json", 
    }).then(function(data) { 
     return data; 
    }, function(err) { 
     // convert failure into success so $.when() doesn't stop 
     return $.Deferred().resolve('err'); 
    })); 
    } 

$.when.apply($, requests).then(callback); 

たとえ何らかの約束が拒否されたとしても、あなたはすべて結果をもたらします

$.when()(最初の拒絶約束で停止する)の代わりに、この新しい機能$.settle()を使用して、すべての約束の結果を返すことができます。 PromiseInspectionオブジェクトの配列を返します。これにより、各約束の解決された値または拒否された理由を照会することができます。

$.when()のように、PromiseInspectionオブジェクトのすべての結果を返し、常に解決します(拒否しない)ことを除いて、$.settle()と同じように使用します。 PromiseInspection.valueが成功AJAX呼び出しから返されたので.settle()のアレイに複数の引数、それをコピーして検出した場合.then()ハンドラ(特にAjaxの呼び出し)に複数の引数を渡すのjQueryの非標準的な手段のので、配列[data, textStatus, jqXHR]です。これはjQueryの非標準的な約束の中で最悪の部分です。これは、標準に準拠しているはずのjQuery 3.xで固定/変更されていると思われます。このコードは、.then()ハンドラに複数の引数が送信された場合に自動検出し、それらを単一の配列引数に変換するので、どちらでも動作します。あなたは、コールのいずれかに障害が発生したときにエラー条件としてあまりに$.when.applythenにエラーコールバックを追加する必要が

// ES6 version of settle 
jQuery.settle = function(promises) { 
    function PromiseInspection(fulfilled, val) { 
     return { 
      isFulfilled: function() { 
       return fulfilled; 
      }, isRejected: function() { 
       return !fulfilled; 
      }, isPending: function() { 
       // PromiseInspection objects created here are never pending 
       return false; 
      }, value: function() { 
       if (!fulfilled) { 
        throw new Error("Can't call .value() on a promise that is not fulfilled"); 
       } 
       return val; 
      }, reason: function() { 
       if (fulfilled) { 
        throw new Error("Can't call .reason() on a promise that is fulfilled"); 
       } 
       return val; 
      } 
     }; 
    } 

    return $.when.apply($, promises.map(function(p) { 
     return p.then(function(val) { 
      if (arguments.length > 1) { 
       val = Array.prototype.slice.call(arguments); 
      } 
      return new PromiseInspection(true, val); 
     }, function(err) { 
      if (arguments.length > 1) { 
       err = Array.prototype.slice.call(arguments); 
      } 
      return new PromiseInspection(false, err); 
     }); 
    })); 
} 

+0

この質問に答えるために、あなたの時間を割いてありがとうございました。私はこの特定のユースケースではより簡単だったという上記の答えを受け入れました。 – mhlavacka

+0

@mhlavackaは - あなたのコールバックがすべての結果を渡されたことを確認したい場合は、いくつかのAJAX呼び出しが失敗した場合でも、その後、私は私の答えの最初にそれを行うには非常に単純な方法を追加しました。それ以外の答えはあなたにすべての結果を与えるわけではありません。コールバックが常に呼び出されることを確認しますが、コールバックが呼び出されたときに必ずしもすべての結果が得られるとは限りません。 – jfriend00

+0

あなたは正しいです、ただ一つのajax呼び出しが失敗した後に停止することを認識しました。 – mhlavacka

1

$.when.apply(undefined, requests).then(
    function(results){callback()}, 
    function(results){callback()} 
); 

ワーキングjsBin here

+0

これですべての結果は得られません。 '$ .when()'は、約束が拒否されるとすぐに結果を収集しなくなります。したがって、ajax呼び出しの1つが失敗した場合、これで完全な結果は得られません。コールバックが常に呼び出されることを保証しますが、コールバックはすべての結果(私はOPが望んだと思ったものです)で呼び出されることはありません。 – jfriend00

+0

それは本当です。失敗したコールを実行しますが、その直後で停止します。 – mhlavacka

関連する問題