2014-10-03 46 views
0

我知道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函數?

+1

在'done()'回調中實現連續代碼。 – 2014-10-03 08:56:23

+0

@Asle使ajax同步可以掛起你的應用程序。如果你希望數據在ajax調用完成時可用嘗試使用回調函數 – 2014-10-03 08:58:51

+0

通常的解決方案是禁用ui,可能會顯示帶覆蓋的ajax微調, - 在ajax回調中啓用。同步ajax鎖定用戶界面,並造成不愉快的體驗 – andrew 2014-10-03 08:59:11

回答

3

異常是我需要從數據庫中立即返回的數據。不過,我需要「連續代碼」來等待Id被返回。

最好的辦法是不要讓這種情況發生,而是要接受事件驅動的,基於瀏覽器和網絡編程的異步性質。

非常小的選項是強制ajax請求同步。目前,在jQuery 1.x中,您可以通過將async: false添加到您的呼叫中來實現此目的;您還必須開始使用自己的$.Deferred而不是從ajax得到的那個,因爲從jQuery 1.8開始,使用async: falsejqXHR的內置許諾已被棄用。所以:

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塊(鎖定了大多數瀏覽器的用戶界面),直至調用完成。由於jQuery的承諾的工作方式,這也將使done回調同步。 (許多其他承諾實現並非如此,但它是jQuery的。)

該選項使用XMLHttpRequest的基本功能,該功能允許同步ajax。

這個選項也會在jQuery中消失。

+1

Thanx!這解決了我的問題。輝煌!終於星期五!;) – 2014-10-03 09:10:18

0

您可以將$ .ajax的async屬性設置爲false。默認情況下是真的。

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

@op我敦促你不要採取這種方法 – andrew 2014-10-03 09:03:41

+0

@andrew,我同意你的看法,那就是回調應該是這種場景的理想人選。 – 2014-10-03 09:05:09