在現代web應用程序中,異步操作是很常見的。異步操作是指可以在同步代碼執行之外調用的代碼。通常,異步操作被用來在客戶端(瀏覽器)和服務器之間進行通信,以允許用戶在不刷新頁面的情況下更新頁面。例如,在用戶與服務器進行交互時,如果數據需要后臺處理,那么用戶需要等待處理完成或者刷新頁面,這樣將會造成用戶不友好及體驗不佳。此時異步操作的作用就被體現出來了, 保障了用戶體驗。
javascript的異步機制通過回調函數的使用來實現。當一個異步操作完成時,將會調用一個回調函數,這個回調函數的作用是通知異步操作完成并且可以處理異步數據。但是在異步操作完之后,如何保存異步數據呢?這是我們今天要討論的問題。
我們來看一下下面的代碼實例,這里我們使用了ajax請求來獲取一篇博客的數據。
//異步請求
$.ajax({
url: "/blog/1",
method: "GET"
}).done(function(data) {
console.log(data);
});
這里我們假設我們需要將data保存在某個地方以便之后使用。但是由于ajax請求是異步的,當異步請求完成時,全局變量或其他任意方式不保證其一定能輸數據的正確保存,而異步操作完成時的回調函數是可以保存數據的。因此我們可以通過回調函數將請求的數據傳遞給外部作用域,或者直接在事件處理函數中處理數據。
//異步請求
$.ajax({
url: "/blog/1",
method: "GET"
}).done(function(data) {
//將數據保存在外部作用域
window.blogData = data;
//或者直接在事件處理函數中處理數據
processData(data);
});
你可能會問,為什么我們不能在全局作用域保存數據?這是因為在javascript中,異步操作完成時請求的數據不會立即返回,當javascript運行到回調函數代碼時代碼往往已經往下執行了。因此,保存數據的辦法是通過將數據傳遞到回調函數中,或者直接在回調函數中處理數據。
下面的例子將使用jquery Deferred對象來保存異步操作的結果。Deferred是jQuery中用于控制異步回調的功能性對象庫。通常來說,您可以把它看做是一種用于管理異步回調的特殊對象。您可以使用它來告訴調用您的代碼何時執行異步回調,以及何時執行失敗回調等等。
//創建Deferred對象
var defer = $.Deferred();
//異步請求
$.ajax({
url: "/blog/1",
method: "GET"
}).done(function(data) {
//將請求數據傳遞給Deferred對象
defer.resolve(data);
});
//等待異步操作完成并處理數據
defer.promise().done(function(data){
processData(data);
});
像前面一樣,我們首先將ajax請求包裝在Deferred對象中。當請求成功時,我們將數據傳遞給Deferred對象。最后,我們等待異步操作完成并處理數據。您可能會問,這不同于前面的代碼示例嗎?是的,但是使用Deferred對象,我們可以更完整地管理異步回調和非異步捕獲。
上面的實現方式,我們通過回調或Promise的方式將數據傳遞出去,從而完成數據的保存,這是非常實用和常見的方法。實現方式雖然多種多樣,但保存異步數據的核心是:異步請求結束后,我們要通過回調或Promise的方式,將異步請求返回的數據傳遞出去,從而在執行的其他代碼/Iframe中進行處理。這樣,就能保證異步請求的數據能被準確地獲取,而不會產生誤判或遺漏,以及操作行為的不同步等問題,從而保證應用程序的持續穩定運行。