在执行下一步JS

时间:2016-03-08 03:03:57

标签: javascript jquery reactjs flux

我有一个数组可以容纳未知数量的索引。每个索引用于通过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;

3 个答案:

答案 0 :(得分:1)

您可以利用$.ajax()实际返回deferred object这一事实,并使用它来创建一个延迟数组。 e.g。

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#call上的Array#prototype循环遍历它。

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

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

现在启动这个递归函数,只需通过传递索引0来启动它。

  AsyncLoopHandler(0);

因此,所有ajax调用将一个接一个地执行,就好像它是一个同步请求一样,并且if检查将查看是否所有索引都已完成,然后运行您的逻辑。如果有帮助,请告诉我

答案 2 :(得分: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 )
});

或在新标准中使用yield和co

https://github.com/kriskowal/q