簡體   English   中英

在執行下一步JS之前需要進行多個Async調用

[英]Need to make multiple Async calls before executing next step JS

我有一個可以容納未知數量索引的數組。 每個索引用於通過ajax調用發送數據。 我正在遍歷for loop ,從成功的調用中收集數據並將其推入一個空數組。 在未知數量的調用結束時,我需要在視圖中使用新收集的數組。 newDataArray在循環完成之前在底部執行,因此它仍然為空。 如何完成所有通話,然后執行底部的操作?

如果有幫助,我將在React中使用Flux模式進行操作。 但是相同的問題可能不會在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;

您可以利用$ .ajax()實際上返回延遲對象的事實,並使用它來創建延遲數組。 例如

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偽數組。 由於參數不是實際的數組,因此我們將在Array#prototype上使用Function#call遍歷它。

$.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);
});

[ 更新為包括fail()調用]

如果您使用的是ES6,這會更加優雅:

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

每當您處理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);
          });
    }  
}

現在,要啟動此遞歸函數,只需通過傳遞索引0即可啟動它。

  AsyncLoopHandler(0);

因此,所有ajax調用將一個接一個地執行,就好像它是一個同步請求一樣,並且if檢查將查看所有索引是否都完整,然后運行您的邏輯。 讓我知道這是否有幫助

建議使用承諾,邏輯要

 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 ) }); 

或在新標准中使用yield和co

https://github.com/kriskowal/q

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM