【轉】javascript的異步概念
某天突然寫了個方法要從後臺調用數據,顯示在前臺頁面,但是輸出結果總是空 undefined,得不到數據。多方找資料才發現,原來是入了 JS 異步的 “坑”。
我們常常聽到單線程、多線程、同步、異步這些概念,那麽這些東西到底是什麽呢? 那麽我們先從上面那幾個概念說起 o( ̄▽ ̄) ブ
單線程、多線程、同步、異步基本理解
每個正在運行的程序(即進程)至少有一個線程,被稱為主線程。主線程在啟動程序時被創建,用於執行 main 函數。
-
單線程就是只有一個主線的線程,代碼從上往下順序運行,主線程負責執行程序的所有代碼(UI 展現以及刷新,網絡請求,本地存儲等等)【一個線程要做所有的事情,想想都有點累呢】
-
多線程顧名思義,就是有多個線程的程序,可以由用戶自主創建。用戶自主創建的若幹進程相對於主線程而言就是子線程。子線程和主線程都是獨立的運行單元,各自的執行互不影響,因此能夠並發執行。
光聽這些幹巴巴的理論是不是覺得有點暈? 巧了,我乍一看的時候也暈。 在找資料的過程中,我發現了別人的這麽一個形象的比喻。
打個比方,單線程就是你去廚房又燒飯又燒菜,一個人來回跑;多線程就是兩個人,一個單做飯,一個單做菜。
這麽說,應該更好理解了吧?
而什麽又是同步和異步呢?
我們用一個簡單的生活例子來說明。
你打電話訂酒店,問工作人員有沒有房間,這時候,工作人員需要查找有沒有房間才能回答你。
-
同步就是不掛電話一直等,直到工作人員告訴你有沒有房間。
-
異步就是掛斷電話,你去做別的事情,比如吃飯喝水,工作人員查到了信息再打電話告訴你。
那麽我們的主題來了
JS 的異步操作是怎樣的呢?
JS 的執行環境是單線程的,也就是說,程序順序執行下來,一次只能執行一個任務,程序想要往下運行,就必須等待當前的任務執行完畢,不管當前的任務要執行多久(要是後面的程序急著跑出來可真的是等的很難受呢)。
為了解決後面程序等的難受的這個阻塞問題。JavaScript 有一種異步處理模式,其實就是延時處理。
我們再來拋出例子來說明。
-
var getUserInfo = function () {
-
$.getJSON("http://www.easy-mock.com/mock/5a09868228b23066479b8379/ajaxData/getUserInfo", function () {
-
return data;
-
});
-
}
-
var data = getUserInfo();
-
renderUserInfo(data)
getUserInfo 這個函數被調用,要取後臺取數據,可能要耗費很多時間,這就要讓 renderUserInfo 一直等著,直到取出 data 才能運行。幸好 JS 有異步操作,取數據的時候,不用 renderUserInfo 一直等著 data 取出來,而是直接執行。
這麽說的話,那麽這兩個函數到底是什麽順序執行的吶?不急,我們來調試一下:
-
var getUserInfo = function () {
-
console.log(‘aaa‘);
-
$.getJSON("http://www.easy-mock.com/mock/5a09868228b23066479b8379/ajaxData/getUserInfo", function () {
-
console.log(‘bbb‘);
-
return data;
-
});
-
}
-
var data = getUserInfo();
-
console.log(data);
-
console.log(‘ccc‘);
-
renderUserInfo(data);
順序執行下來的輸出原以為是 "aaa","bbb","ccc" 吧?
然而事情並沒有這麽簡單。我們來看一下控制臺的輸出:
輸出的結果竟然不是順序的。 也就是說函數執行到 getJSON 取數據的時候,程序並沒有等它取出數據再執行下一步,而是跳過了取數據這一個階段,直接執行輸出 data 了,因此,data 也為空。
這就是 JS 的異步機制了。
自我總結:這個例子中的$.getJSON方法,是可以帶入一個回調函數的,有了回調函數之後,可以在執行長時間的進程,同時操作了回調函數的內容。
【轉】javascript的異步概念