强制Chrome检查$ .ajax通话是否已完成?

时间:2016-11-13 19:14:58

标签: javascript jquery ajax google-chrome

下午好人 -

是否有一种众所周知的方法可以检查$.ajax来电是否已完成?

- FOR INSTANCE -

让我们说我使用$.ajax调用从.geojson文件中加载大量的传单多边形(异步作为图层组)。在正常情况下,这几乎立即发生 - 但是这次用户选择加载大量工作。用户假设已经加载了多边形集并试图过早地对这组图层执行某些操作 - 只发现没有任何反应(图层组在浏览器中实际上还没有存在)。

我的直觉(我对Web开发不熟悉)是要为依赖算法设置某种全局标志来检查。我们会在加载图层之前设置标记,然后将其更改为.done({})调用的$.ajax部分中的其他值。

- 更新 -

我已经重新设计了代码,允许用户选择是否要重试请求,并强制浏览器等待一段时间再重试请求。

但是,我也发现问题似乎与Chrome有关。 Firefox似乎能够在完成后立即处理$ .ajax.always回调(换句话说,$ .ajax.always回调将中断常规的javascript流)。

Chrome似乎会阻止$ .ajax.always回调,只允许它在所有其他javascript运行完毕后执行(无中断)。

这个特殊的问题源于一个调试案例,它可以自动从循环中输入用户 - 而且由于Chrome在当前流程完成之前没有调用$ .ajax.always回调,因此该流程不是标记为已完成。

示例代码:

procBox = []; // Global scope, stands for Process Box

function loadPolygons() {
    procBox["loadPolygons"] = "running";

    $.ajax({
        // ajax things here 

    }).done(function() {
         procBox["loadPolygons"] = "done";
    }).fail(function() {
         // failure stuff here
    });
}

function dependentFunction() {
    if procBox["loadPolygons"] === "done") {
        // The meat of the function (dependentFunction things here)

    } else {
        // Backup case that allows the browser to retry the request
        /* --
         * If this fires, the server is still trying to process the 
         * ajax request. The user will be prompted to retry the request,
         * and upon agreement, the function will be called again after
         * 1 second passes.
         */

        var msg = "Oops! It looks like we're still fetching your "
                + "polygons from the server. Press OK to retry.";

        if (confirm(msg)) {
            setTimeout(dependentFunction, 1000);
        }
    }
}

这种方法似乎在Firefox中运行良好 - alert()阻止了JavaScript执行,并为.done({})回调提供了机会。但由于某种原因,while循环永远不允许在Chrome中完成.done({})回调!

有没有人比使用旗帜或async: false知道更好的方法呢? 我感谢那里的任何答案和知识!

2 个答案:

答案 0 :(得分:0)

有很多方法可以做: 已经sugegsted你可以使用 因为你使用jQuery,你可以使用自定义事件https://learn.jquery.com/events/introduction-to-custom-events/

$(document).on("myajax:done", function(){ dependentFunction();})
$.ajax({...}).done(function(){
    $(document).trigger("myajax:done")
}); 

甚至是全球的ajax事件 https://api.jquery.com/category/ajax/global-ajax-event-handlers/

但是真的考虑为什么不做像

这样的事情
procBox = {onLoadPolygons:dependentFunction}; // Global scope

function loadPolygons() {
    $.ajax({
        // ajax things here 

    }).done(function() {
         procBox["onLoadPolygons"]();
    }).fail(function() {
         // failure stuff here
    });
}

function dependentFunction() {
        alert("Please wait for the polygons to load");
     dependentFunctionThings();

}
function dependentFunctionThings(){
    // Do dependent function things...
}

UPD: 如果你坚持你的结构,仍然想使用阻止功能 使用 setInterval 执行检查

function dependentFunction() {
    var h = setInterval(function() {
         if (procBox["loadPolygons"] == "done") { 
             clearInterval(h);
            // Do dependent function things...
        }
    }, 100);
}

或将其包装成Promise(http://caniuse.com/#feat=promises

function dependentFunction() {
   (new Promise(function(resolve) {
      var h = setInterval(function(){
         if (procBox["loadPolygons"] == "done") { 
             clearInterval(h);resolve(); 
         }

      }, 100);
   })).then(function(){
       // Do dependent function things...
   });
}

但我仍然认为你的结构有问题

答案 1 :(得分:-1)

来自文档:

.ajaxComplete()

每当Ajax请求完成时,jQuery就会触发ajaxComplete事件。已经使用.ajaxComplete()方法注册的任何和所有处理程序都会在此时执行。

http://api.jquery.com/ajaxcomplete/