2016-03-08 59 views
0

我有一個數組,它可以容納未知數量的索引。每個索引用於通過ajax呼叫發送數據。我正在通過for loop收集成功調用的數據並將其推入空數組。在未知數量的調用結束時,我需要在我的視圖中使用新聚集的數組。 newDataArray在循環完成之前在底部執行,因此它仍然是空的。我如何完成所有的電話,然後做底部的事情?在執行下一步之前需要進行多個異步調用JS

如果有幫助,我正在使用Flux模式進行React。但是同樣的問題可能不會在React中完成。這裏是什麼,我試圖做一個模擬樣本:

JS

case 'execute-calls': 

    //This is the new array to push to 
    var newDataArray = []; 
    //Url to call 
    var url = 'http://dev.markitondemand.com/Api/v2/Quote/jsonp'; 

    for(let i = 0; i < payload.data.length; i++){ 

     //given array of data that needs to be sent with call 
     let symb = { symbol: payload.data[i]}; 
     $.ajax({ 
      data: symb, 
      url: url, 
      dataType: "jsonp", 
     }) 
      .done(function(data){ 
      let updatedData = { 
       //...data that is stored from response 
      }; 

      newDataArray.push(updatedData); 
      }) 
      .fail(function(error){ 
      //console.log(error); 
      }); 

     } 

    //This will be updating the state object which is above the switch cases 
    //However this is ran before the end of the loops so newDataArray is empty 
    var updateTicker = { 
     updatedTicker: true, 
     updatedTickerSymbols: newDataArray 
    }; 
    assign(stockData,updateTicker); 
    getStockData.emitChange(); 

    break; 

回答

1

可以使使用$.ajax()實際返回deferred object ,並用它來創建一個延遲數組。例如

var symbols = [1, 2, 3, 4]; 

var deferreds = symbols.map(function (symbol) { 
    return $.ajax({ 
    url: 'http://dev.markitondemand.com/MODApis/Api/v2/Quote/jsonp', 
    data: { symbol: symbol }, 
    dataType: 'jsonp' 
    }); 
}); 

您可以用$.when()一次解決多個延期。但是有一個複雜的問題,$ .when()需要一個參數列表而不是數組。我們可以通過使用Function#apply來解決這個問題。

要添加到併發症,回調函數也被稱爲參數列表。由於我們不知道有多少個參數,我們將使用arguments僞數組。由於參數不是實際的數組,我們將通過使用Function#callArray#prototype進行循環。

$.when(...deferreds).done((...responses) => { 
    responses.forEach((response) => { 
    console.log(response[0].Message); 
    }); 
}); 
+0

這種方式似乎最直觀:

$.when.apply($, deferreds).done(function() { Array.prototype.forEach.call(arguments, function (response) { console.log(response[0].Message); }); }).fail(function (jqXHR, textStatus, error) { console.error(error); }); 

如果您使用ES6這是更優雅[修訂包括失敗()調用]

。感謝你的回答。你如何看到從響應中是否發生錯誤?它會被存儲在其中一個索引中嗎? '$ .when.apply($,deferreds).done(function(response){'那裏的控制檯日誌記錄響應會顯示錯誤? – Chipe

+1

好點,還有一個失敗的回調函數,當遇到第一個錯誤時會調用它我相應地更新了代碼。 –

0

當過你正在處理Ajax調用,並有在所有異步年底做一些操作調用,那麼更好的選擇會是使用Callback函數。

修改代碼以使用回調,

function AsyncLoopHandler(index) { 
    if (index > payload.data.length) { 
     // all the indexes have finished ajax calls do your next step here 

     var updateTicker = { 
      updatedTicker: true, 
      updatedTickerSymbols: newDataArray 
     }; 
     assign(stockData, updateTicker); 
     getStockData.emitChange(); 
    } 
    else { 
     //given array of data that needs to be sent with call 
     let symb = { symbol: payload.data[index] }; 
     $.ajax({ 
      data: symb, 
      url: url, 
      dataType: "jsonp", 
     }) 
      .done(function (data) { 
       let updatedData = { 
        //...data that is stored from response 
       }; 

       newDataArray.push(updatedData); 
       AsyncLoopHandler(index++); // call the function again with new index 
      }) 
      .fail(function (error) { 
       //console.log(error); 
      }); 
    } 
} 

現在啓動這個遞歸函數只是路過

AsyncLoopHandler(0); 

因此,所有的Ajax調用將被執行的索引0

啓動如同一個同步請求一樣,並且 if檢查將會看看所有的索引是否完整,然後運行你的邏輯。讓我知道,如果這有助於

0

建議使用承諾,邏輯想在新標準

var urls= [x,x,x,x]; 
 
var results = []; 
 
var qs = $.map(urls,function(url){ 
 
    return function(){ 
 
    var deferred = Q.defer(); 
 
    $.ajax({ 
 
     success:function(){ 
 
     results.push(url) 
 
     deferred.reslove(); 
 
     },error:function(){ 
 
     deferred.reslove();   
 
     } 
 
    }) 
 
    return deferred; 
 
    } 
 
}) 
 
Q.all(qs).then(function(){ 
 
    console.log(results) 
 
});

或使用產量和合作https://github.com/kriskowal/q