如何使AJAX同步

时间:2014-10-03 08:54:03

标签: jquery ajax

我知道Ajax的本质是异步的,因此我的代码是错误的。 但我需要帮助才能找到另一种解决方案。

案例是:我将数据插入到我的数据库中:

 self.insertTextItem = function (item) {
    console.log("Insert TextItem with Service");
    return $.ajax({    
        type: "POST",
        url: serviceRoot + "InsertTextbatchTagItem",
        beforeSend: serviceFramework.setModuleHeaders,
        data: item,
        cache: false
    });
};

item.Id = null; // Id is autocreated in db.
item.Text = "Finally Friday!";

self.insertTextItem(item)     
    .done(function (newtext) {
                item.textbatchId = newtext.Id;
}

//continuous code…

在大多数情况下,这可以找到。 例外情况是我需要立即从数据库返回的数据。 但是我需要"连续代码"等待Id返回。 显而易见的解决方案是放置连续代码"进入回调函数,但实际上,我在函数中调用self.insertTextItem,因此调用函数返回而不等待。 (显然回调函数在调用函数中结束。)

在这种情况下如何重写self.insertTextItem函数?

2 个答案:

答案 0 :(得分:4)

  

异常是我需要立即从数据库返回的数据。但是我需要"连续代码"等待Id返回。

你最好的选择不是让这种情况发生,而是接受基于浏览器和网络编程的事件驱动的异步性质。

非常小的选项是强制ajax请求同步。目前,在jQuery 1.x中,您可以通过在呼叫中添加async: false来实现此目的;您还必须开始使用自己的$.Deferred而不是ajax获得的{1}},因为从jQuery 1.8开始,async: false使用jqXHR& #39;内置的承诺已被弃用。所以:

self.insertTextItem = function (item, synchronous) { // <== Optional flag
    var deferred = $.Deferred();                     // <== Your own Deferred
    console.log("Insert TextItem with Service");
    $.ajax({    
        type: "POST",
        url: serviceRoot + "InsertTextbatchTagItem",
        beforeSend: serviceFramework.setModuleHeaders,
        data: item,
        cache: false,
        async: synchronous === true ? false : true,  // <=== Use it, ignoring `undefined` and othe rfalsey values
        success: function(data) {                    // Handling you Deferred
            deferred.resolveWith(data);              // (this is probably incomplete)
        },                                           //
        error: function() {                          //
            deferred.reject();                       //
        }                                            //
    });
    return deferred.promise();                       // Return the promise for your Deferred
};

这将使insertTextItem阻止(锁定大多数浏览器的UI),直到调用完成。由于jQuery的承诺有效,这也会使done回调同步。 (许多其他的promises实现都不是这样,但它是jQuery的。)

该选项使用XMLHttpRequest的基础功能,允许同步ajax。

该选项在某些时候也将在jQuery中消失。

答案 1 :(得分:0)

您可以将$ .ajax的async属性设置为false。默认情况下,这是真的。

$.ajax({    
        type: "POST",
        async : false,
        url: serviceRoot + "InsertTextbatchTagItem",
        beforeSend: serviceFramework.setModuleHeaders,
        data: item,
        cache: false
    });