【问题标题】:Array of multiple ajax deferred calls processed in an asynchronous code block followed by synchronous final code block在异步代码块中处理的多个 ajax 延迟调用数组,后跟同步最终代码块
【发布时间】:2015-11-18 04:08:13
【问题描述】:

我是 jquery 和 ajax 的新手,我正在尝试使用延迟和承诺的概念来解决我遇到的这个问题。 我想做以下事情: 调用 URL 列表并处理从 url 返回的结果。我想先并行处理结果,然后将处理后的结果结合起来给我一个最终的结果。

伪代码如下:

var deferredAjaxCalls = [];
for (var i = 0; i < jobsListLength; i++) {
    deferredAjaxCalls.push(
        $.ajax({
            url:"/myurl",
            method:"POST",
            contentType:"application/json",
            dataType:"json",
            data:mydata,
            success:function(result){
              //Some code here that is performance intensive
            } 
        });
}
$.when.apply(this,deferredAjaxCalls).done(function(){
    for (var k=0; k< arguments.length;k++){
            //combine the results of the individual results of the
            // success part of all the ajax calls and execute some more 
            //code synchronously
    } 
}).fail( function (jqXHR, status, error) {
   //Log failed status
 });

最初,我将所有代码从成功部分移到 $.when.apply() 中。但是,这导致性能非常慢,因为现在有很多密集的计算是同步执行的。所以我正在寻找一种方法来独立执行部分代码,并同步执行最后一段

我确实读过有关使用 Promise 的信息,但找不到任何示例,其中 Promise 与带有中间处理的 ajax 调用数组一起使用,然后最终在 when.apply() 块中进行同步

什么是解决这个问题的好方法?

谢谢!

【问题讨论】:

    标签: javascript jquery ajax jquery-deferred


    【解决方案1】:

    从数组jobsList 开始,您可能想要这样的东西:

    var deferredAjaxCalls = jobsList.map(function(job) {
        return $.ajax({
            url: "/myurl",
            method: "POST",
            contentType: "application/json",
            dataType: "json",
            data: mydata
        }).then(process);// where `process` is a function that accepts $.ajax's (data, textStatus, jqXHR) and returns a *single* value/object - the result of the processing. This will standardise the data delivered below by $.when() to its success handler.
    });
    $.when.apply(null, deferredAjaxCalls).then(function() {
        // Due to `.then(process)` above, `arguments` are guaranteed to comprise one arg per ajax call.
        // Otherwise you potentially have the problem reported here - http://stackoverflow.com/questions/12050160/
        for (var k=0; k<arguments.length; k++) {
            // Combine the results of the individual results of the success part of all the ajax calls and execute some more code synchronously.
        }
        // In this function deliver an error by returning `$.Deferred().reject(new Error('myReason'))`
        return combined_result;
    }, function(jqXHR, status, error) {
        // This hander will receive multiple $.ajax() params, which are best normalised into a single Error object. 
        return new Error(status); // similar to .then(process) above, reduce $.ajax's error args to a single "reason".
    }).then(null, function(err) {
        // All errors delivered by code above arrive here as a js Error.
        // But please note that, in jQuery <v3.0, any uncaught errors above will genuinely throw (to the console).
        console.log(err.message);
    });
    

    【讨论】:

      【解决方案2】:

      您可以尝试使用延迟:

        var req_responses = [];
        var deferreds = [];
      
        for(var i in jobs) {
           deferreds[i] = new $.Deferred();
        }
      
        for(var i in jobs) {
           (function(i) {
              $.ajax ({
                 url: ".",
                 type: "POST",
                 dataType: "json",
                 done: function(response) {
                    //process the response
                    req_responses[i] = response;
                    deferreds[i].resolve();
                 }
              });
           })(i);   
        }
      
        $.when.apply(deferreds).then(function(os) {
           //all the responses are in req_responses
           //finish processing
           alert("done");
        });
      

      【讨论】:

      • 请不要!使用已经返回承诺的异步进程交付的结果来解决延迟(或承诺)被称为explicit promise construction antipattern,应该避免。而$.ajax() 有一个success: 选项,它还返回一个promise,它本身可以返回和/或用作promise 链的前导元素。
      • 有趣。那么解决方案是只使用done回调而不是success?
      • Dane,更可能是.then(),这将允许返回处理后的结果以传递到承诺链(进入 $.when(...).then() 的处理程序中案例)。
      猜你喜欢
      • 1970-01-01
      • 2011-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      相关资源
      最近更新 更多