同步Ajax请求“锁定”浏览器

时间:2014-10-22 08:51:08

标签: javascript jquery ajax browser synchronous

我有几个jQuery Ajax请求,它们必须是同步的,但它们会一直锁定/冻结浏览器,直到收到响应。我的主要问题是,在收到回复之前我必须显示旋转图标,但由于冻结,微调器不会显示,即使它奇迹般地没有动画。

这是显示微调器并发送请求的事件:

$(document).on('click', '#open-button', function () {

    var input = "some text";
    var wrapper = $('#wrapperWindow');
    wrapper.children().animate({
        opacity: 0
    }, 500);
    wrapper.children().remove();
    wrapper.append('<div id="loading-spinner" style="display:none;"></div>');
    var spinner = $('#loading-spinner');
    spinner.css({
        backgroundImage: 'url("img/loading.gif")',
        opacity: 0
    });
    spinner.show();
    spinner.animate({
        opacity: 1
    }, 500);

    var dataForTab = requestData(input); //<-- the request

    if (dataForTab.length > 0) {
        //do stuff
    }

});

请求:

function requestData(input) {

    var result = null;

    $.ajax({
        async: false,
        type: "POST",
        url: "/some/url?input=" + input,
        dataType: "json",
        retryLimit: 3,

        success: function (json) {
            result = json;
        },

        error: function (xhr, err) {
            console.log(xhr);
            console.log(err);
        }
    });

    return result;
}

在请求返回收到的JSON数据之前,所有内容都会停止移动。我该如何解决这个问题呢?

2 个答案:

答案 0 :(得分:4)

这是同步请求的本质,它们是锁定的。您可能希望尝试将请求移至web worker。这里是example(不使用XHR,但它可以为您提供实施方案)

Web worker在单独的文件中实现,脚本可以如下所示:

onmessage = function (e) {
var result = null;

    $.ajax({
        async: false,
        type: "POST",
        url: "/some/url?input=" + input,
        dataType: "json",
        retryLimit: 3,

        success: function (json) {
            result = json;
            postMessage({result: result});
        },

        error: function (xhr, err) {
            postMessage({error: err});
        }
    });

}

答案 1 :(得分:0)

根据您的使用情况,您可以使用类似

的内容
  

task.js 简化界面,让CPU密集型代码在所有核心(node.js和web)上运行

一个例子是

// turn blocking pure function into a worker task
const syncWorkerRequest = task.wrap(function (url) {
    // sync request logic
});

// run task on a autoscaling worker pool
syncWorkerRequest('./bla').then(result => {
    // do something with result
});

你不应该这样做,除非你需要做一些繁重的数据处理,请使用异步请求。