1

これが私の問題の説明です:

いくつかのflickrフォトセットのIDを含む配列があります。IDごとに、2つのネストされたapiCall(1つはflickr photosets api、もう1つはphotoinfo api)を作成し、ページにhtmlを追加する必要があります。

構造は次のとおりです。

for(var i=0; i<ARRAY_ID.length; i++){

    $.getJSON(apiCall, function(data) {
         // some processing here

         $.getJSON(apiCall2,function(data){
              //other processing here

各「apiCall」は、フォトセットapi(apiCall)への正しい呼び出しと、photoInfo api(apiCall2)への正しい呼び出しを含む文字列です。

このすべての処理の後、「apiCall2」ブロック内で、いくつかのhtmlをdivに追加します(これにより、ARRAY_IDの長さと同じ数のブロック要素が生成されます)。

私が奇妙な振る舞いをしているところがあります:追加されたすべてのブロック要素には、同じテキストと画像とリンクが含まれています。期待した数で印刷されますが、内容はすべて同じです。$.getJSONが終了するのを待たないforループだと思います。どうすればこれを達成できますか?次のリクエストが処理される前に、各jsonリクエストを完了する必要があります。皆さんありがとう!

4

3 に答える 3

4

ここに2つの異なるが関連する問題があるようです。


追加されたすべてのブロック要素には、同じテキストと画像とリンクが含まれています。予想される数でそれらを出力しますが、内容はすべて同じです。

iコールバック内で参照している場合は、 for. それ以外の場合、$.getJSON非同期であるため、forはコールバックが呼び出される前に終了し、i常にループ内の最後の値になります -- ARRAY_ID.length:

for(var i = 0; i < ARRAY_ID.length; i++) {
    (function (i) {
        // work with the local `i` rather than the shared `i` from the loop
    })(i);
}

$.getJSON が終了するのを待っていないのは for ループだと思います。どうすればこれを達成できますか? 次のリクエストが処理される前に、各 json リクエストを完了する必要があります。

forの各セットが終了するまで「待機」することはできません$.getJSON。ただし、forループとクロージャを使用してqueuenextを構築できます。これは、明示的に続行するように指示するまで待機します。

var focus = $(...); // either match an existing element or create one: '<div />'

for(var i = 0; i < ARRAY_ID.length; i++) {
    (function (i) {
        focus.queue('apicalls', function (next) {
            $.getJSON(apiCall, function(data) {
                 // some processing here

                 $.getJSON(apiCall2,function(data){
                      //other processing here

                      next(); // start the next set of api calls
                 });
            });
        });
    })(i);
}

focus.dequeue('apicalls');
于 2012-04-23T20:36:37.653 に答える
1

これはクロージャーによくある問題です。コールバックは、for ループを含む関数のコンテキストから変数を継承しています (メイン関数と呼びます)。これを試して:

for(var i=0; i<ARRAY_ID.length; i++){

    $.getJSON(apiCall, (function(i, v1, v2, etc) { return function(data) {
        // some processing here


        $.getJSON(apiCall2,function(data){
        //other processing here
    })(i, v2, v3, etc));
}

基本的に、クロージャーが変数にアクセスするコンテキストを変更しています。無名関数を作成し、メイン関数からアクセスしているすべての変数を渡します。この例では、変数 i を渡しています。v1、v2 などは、アクセスする可能性のある他の変数を示しています。

クロージャー呼び出しごとに適切なコンテキストを作成することで、この問題を解決できるはずです。

于 2012-04-23T20:31:36.830 に答える
1

ほとんどの場合、スコープの問題です。

getJSON メソッドに渡されたコールバックがiループの変数を使用する場合、ほとんどの場合、それらはすべて の最後の値を使用して終了しますi

解決策は

function handleJsonRequests(index,id){
 // use index instead of i
 // use id instead of ARRAY_ID[i]

 $.getJSON(apiCall, function(data) {
         // some processing here

         $.getJSON(apiCall2,function(data){
              //other processing here

}// end of function

for(var i=0; i<ARRAY_ID.length; i++){
    handleJsonRequests(i, ARRAY_ID[i]);
}
于 2012-04-23T20:32:08.873 に答える