我知道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函数?
答案 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
});