摘要:同步與異步以上為同步代碼,函數(shù)必須等函數(shù)執(zhí)行完畢后才能執(zhí)行。異步回調(diào)產(chǎn)生的結(jié)果就是,函數(shù)的調(diào)用并不直接返回結(jié)果,而往往是交給回調(diào)函數(shù)進行異步處理。
同步與異步:
function a(){} function b(){} a(); b();
以上為同步代碼,函數(shù)b必須等函數(shù)a執(zhí)行完畢后才能執(zhí)行。
function a(){ setTimeout(function(){ b(); }, 1000); }; function c(){}; a(); c();
首先執(zhí)行函數(shù)a,而且不等setTimeout執(zhí)行就執(zhí)行函數(shù)c,等待至少1s的時候后才會執(zhí)行函數(shù)b.實際上在是等待了1s后將函數(shù)b放到了event queue里面,此時要等待主線程空閑的時候,才會取event queue里面等待的回調(diào)函數(shù)進行執(zhí)行。
以上是一段簡單的異步代碼,js里面最基礎(chǔ)的異步實現(xiàn)就是調(diào)用setTimeout,setInterval。
關(guān)于js的異步實現(xiàn)請看下面的list:
談談javascript的異步實現(xiàn)
回調(diào)函數(shù):在js里面簡單點來說,就是函數(shù)被當作參數(shù)傳入另外一個函數(shù)當中,并在那個函數(shù)中被調(diào)用。
var b = function (){ //執(zhí)行相關(guān)的代碼 } var a = function (b){ //執(zhí)行相關(guān)的代碼 b(); } a(b);異步與回調(diào):
大家可能平時聽的比較多的是異步回調(diào),但是必須搞清楚,異步與回調(diào)并沒有直接的聯(lián)系,回調(diào)只是異步的一種實現(xiàn)方式。
當然還有同步回調(diào),即上面回調(diào)部分舉的簡單的例子。一般使用回調(diào)函數(shù)主要是將父函數(shù)的執(zhí)行結(jié)果通知給回調(diào)函數(shù)進行處理。
關(guān)于異步我的理解是:
因為js是單線程的,如果所有的操作(如ajax操作,獲取遠程的js文件等IO操作)是同步的,遇到那些耗時的操作,后面的程序必然被阻塞不能執(zhí)行,頁面也就失去了響應。因此js采用了事件驅(qū)動機制,在單線程模型下,使用異步回調(diào)函數(shù)的方式來實現(xiàn)非阻塞的IO操作。
異步任務 是指js在主線程(stack)運行的過程當中,當stack空閑的時候,主線程對event queque輪詢(事實上一直在輪詢)后,將異步任務放到stack里面進行執(zhí)行。簡單點說,只要指定過回調(diào)函數(shù),那么當這些事件發(fā)生的時候就會進入事件隊列,等待主線程的stack空閑的時候,就會對event queue里面的回調(diào)讀取并放到stack里面執(zhí)行。
看一段ajax實現(xiàn)的代碼:
var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); //第三個參數(shù)決定是否采用異步的方式 xhr.send(data); xhr.onreadystatechange = function(){ if(xhr.readystate === 4 && xhr.status === 200){ ///xxxx } }
這里ajax請求是異步的,因為瀏覽器會新開一個線程請求,當請求的狀態(tài)(readystate)發(fā)生改變,因為之前就設置了回調(diào)函數(shù),每次狀態(tài)發(fā)生改變都會調(diào)用相應的回調(diào)函數(shù),當(xhr.readystate === 4 && xhr.status === 200)的時候,回調(diào)函數(shù)進入了event queue,等待主線程空閑的時候,并且event queue里面排在這個回調(diào)前面沒有其他回調(diào)的時候就會得到執(zhí)行。
異步回調(diào)產(chǎn)生的結(jié)果就是,函數(shù)的調(diào)用并不直接返回結(jié)果,而往往是交給回調(diào)函數(shù)進行異步處理。
因此在異步編程當中,需要注意幾個地方:
需要把依賴于異步函數(shù)(需要其執(zhí)行結(jié)果或者達到某種狀態(tài))的代碼放在對應的回調(diào)函數(shù)中(例如上面的ajax的例子)
異步函數(shù)后面的代碼會立即執(zhí)行(因此需要知道某段代碼是否為異步的)
另外還有一個關(guān)于script標簽異步加載的內(nèi)容:
大家記得請求遠程腳本標簽嗎?
在script標簽里面加入了async屬性或者defer屬性后,同樣變成了異步了。
關(guān)于這部分的內(nèi)容,請移步:
async和defer的區(qū)別
另外關(guān)于這部分的內(nèi)容還有一些List:
并發(fā)模型與event loop
樸靈評阮老師的event loop
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/86138.html
摘要:而是在調(diào)用發(fā)出后,被調(diào)用者通過狀態(tài)通知來通知調(diào)用者,或通過回調(diào)函數(shù)處理這個調(diào)用。請求程序發(fā)出請求,從服務器端獲取數(shù)據(jù),并設置了回調(diào)函數(shù)。然后,瀏覽器會設置偵聽來自網(wǎng)絡的響應,拿到數(shù)據(jù)后,將該回調(diào)函數(shù)插入到事件循環(huán)。 并發(fā)與并行 并發(fā)是指兩個或多個事件鏈隨時間發(fā)展交替執(zhí)行,以至于從更高的層次來看,就像是同時運行(但在任意時刻只處理一個事件) 并發(fā)的關(guān)鍵是你有處理多個任務的能力,不一定同...
摘要:回調(diào)函數(shù),一般在同步情境下是最后執(zhí)行的,而在異步情境下有可能不執(zhí)行,因為事件沒有被觸發(fā)或者條件不滿足。同步方式請求異步同步請求當請求開始發(fā)送時,瀏覽器事件線程通知主線程,讓線程發(fā)送數(shù)據(jù)請求,主線程收到 一直以來都知道JavaScript是一門單線程語言,在筆試過程中不斷的遇到一些輸出結(jié)果的問題,考量的是對異步編程掌握情況。一般被問到異步的時候腦子里第一反應就是Ajax,setTimse...
摘要:例如處理請求的線程處理事件的線程定時器線程讀寫文件的線程例如在中等等。事件循環(huán)事件循環(huán)是指主線程重復從消息隊列中取消息執(zhí)行的過程。事件觸發(fā)時,表示異步任務完成,會將事件監(jiān)聽器函數(shù)封裝成一條消息放到消息隊列中,等待主線程執(zhí)行。 一. 單線程 我們常說JavaScript是單線程的。 所謂單線程,是指在JS引擎中負責解釋和執(zhí)行JavaScript代碼的線程只有一個。不妨叫它主線程。 但是實...
摘要:單線程異步非阻塞然后,這又牽扯到了事件循環(huán)消息隊列,還有微任務宏任務這些。此步的位置不確定某個時刻后,定時器觸發(fā)線程通知事件觸發(fā)線程,事件觸發(fā)線程將回調(diào)函數(shù)加入消息隊列隊尾,等待引擎線程執(zhí)行。 前言 Philip Roberts 在演講 great talk at JSConf on the event loop 中說:要是用一句話來形容 JavaScript,我可能會這樣: Java...
閱讀 3683·2023-04-26 02:32
閱讀 4077·2021-11-23 10:05
閱讀 2331·2021-10-08 10:04
閱讀 2777·2021-09-22 16:06
閱讀 3657·2021-09-22 15:27
閱讀 799·2019-08-30 15:54
閱讀 1788·2019-08-30 13:50
閱讀 2738·2019-08-29 13:56