Javascript非同步程式設計總結
前言
由於js涉及dom互動,如果多執行緒會出現很複雜當執行緒同步問題,故js是單執行緒模式,單執行緒模式指執行程式碼當執行緒只有一個,故每次只能執行一個任務
單執行緒當優點為簡單,安全,缺點為耗時任務會阻塞程式碼執行,出現白屏假死等影響體驗的現象
故為了解決阻塞問題,js將任務的執行分為同步和非同步兩種模式
同步模式
指程式碼中任務依次執行,後一個任務必須等前一個任務執行完畢才會執行,任務等執行順序與程式碼的編寫順序一致,大部分任務均為同步執行
當程式碼載入進來後,會由自執行函式包裹所有程式碼,按照從上倒下,先把第一行放到呼叫棧,當程式碼執行完畢,彈出程式碼,再執行下一行程式碼,知道都執行完畢
非同步模式
不會等待任務執行完畢,才去執行下一任務,開啟以後就會執行下一個任務,後續的處理邏輯會通過回撥函式方式處理
在主執行緒外開闢新的執行緒,在不阻塞主執行緒程式碼大情況下,用於處理一些耗時或計算量大的任務,當非同步結束後,把回撥函式加入到訊息佇列中,等待事件迴圈的呼叫
EventLoop
事件迴圈會監聽呼叫棧和佇列,在呼叫棧空了後,事件迴圈會從佇列中拿出第一個任務,放到呼叫棧中執行,執行完畢後,再拿出下一個任務,依次迴圈
訊息佇列
訊息佇列是儲存待執行的非同步回撥函式,並供事件迴圈呼叫當場所,當非同步程式碼觸發回撥函式時,會把此函式放在佇列末尾,事件迴圈每次在佇列當最前方取出函式去執行
巨集任務與微任務
微任務有js的Promise和nodejs的process.nexttick等
巨集任務有setTimeout,setInterval,js主程式碼等
巨集任務和微任務是相對於非同步程式碼的,在事件迴圈時,當微任務佇列中存在任務,那麼會先呼叫所有微任務,全部執行完畢,再去呼叫第一個巨集任務,依次迴圈
非同步模式執行步驟
console.log('begin')
setTimeout(function timer1 () {
console.log('timer1')
}, 1800)
console.log('end')
上方簡單的非同步程式碼,首先載入完所有程式碼後,會把程式碼放入一個自執行函式並把第一行同步程式碼壓入呼叫棧,執行完畢後列印begin,然後把定時器壓入呼叫棧,會開啟一個執行緒用於計時,然後推出,再把end列印壓入呼叫棧,列印end,再推出,執行完畢,呼叫棧為空
當計時到1.8s時,會把定時器的回撥函式放到訊息佇列,事件迴圈監聽到佇列變更後,在呼叫棧為空時,會把佇列的第一個推入呼叫棧(如果此時有微任務,會執行完所有微任務再執行此操作),執行定時器的回撥函式,列印timer1
Promise
非同步程式設計的根基是回撥函式,而傳統的回撥函式巢狀寫法,很難維護與閱讀,promise可以使非同步程式設計更可維護與閱讀
new Promise(function (resolve, reject) {
// 同步執行此函式體
setTimeout(() => resolve(1))
}).then((v) => {
console.log(v); // 1
});
狀態有fulFilled(成功,對應resolve,執行then的第一個引數),rejected(失敗,對應rejected,執行catch回撥或then的第二個引數)
Promise.all()
引數為Promise物件組成的陣列,返回新的Promise,當陣列中所有的Promise的狀態均為fulFilled,執行then回撥,引數為所有Promise的返回值組成的陣列,此陣列與傳入陣列一一對應,否則執行catch
Promise.race()
引數為Promise物件組成的陣列,返回新的Promise,當陣列中有一個任務結束,則直接按照該任務的狀態返回
Promise.resolve()
快速把值轉化為Promise物件,並執行then的第一個引數,如傳入Promise物件,會直接返回
Promise.reject()
快速把值轉化為Promise物件,並執行then的第二個引數,如傳入Promise物件,會直接返回
Promise.finally()
引數為函式,返回值為Promise物件,不論成功或失敗均會呼叫,並且所傳函式呼叫時沒有引數,會把當前Promise的成功或失敗的值,傳遞給返回的新的Promise物件
Generator
使用*和yield關鍵字,當呼叫函式時,不會直接執行,而是會返回Generator物件,當呼叫物件當next方法時,才會執行,並且遇到yield關鍵字會停止執行,直到再次呼叫next方法
function * foo () {
const res = yield 'foo';
return res;
}
const generator = foo()
const result = generator.next(); // foo
因為每次均須手動呼叫next方法,所以需要一個執行器去自動執行所有next方法
function co (generator) {
const g = generator()
function handleResult (result) {
if (result.done) return // 生成器函式結束
result.value.then(data => {
handleResult(g.next(data))
}, error => {
g.throw(error)
})
}
handleResult(g.next())
}
co(foo)
async await
async await是generator的語法糖,可不用自己呼叫自己封裝執行器,看起來更像同步程式碼
async function main () {
const users = await ajax('/api/users.json')
const posts = await ajax('/api/posts.json')
const urls = await ajax('/api/urls.json')
}
相關文章
- Flutter 中的非同步程式設計總結Flutter非同步程式設計
- Javascript 非同步程式設計JavaScript非同步程式設計
- JavaScript非同步程式設計JavaScript非同步程式設計
- 總結非同步程式設計的六種方式非同步程式設計
- 【Javascript】DOM程式設計學習總結篇JavaScript程式設計
- JavaScript設計模式總結JavaScript設計模式
- 探索Javascript非同步程式設計JavaScript非同步程式設計
- 前端排序演算法總結;前端面試題2.0;JavaScript非同步程式設計前端排序演算法面試題JavaScript非同步程式設計
- 你好,JavaScript非同步程式設計—- 理解JavaScript非同步的美妙JavaScript非同步程式設計
- 你好,JavaScript非同步程式設計---- 理解JavaScript非同步的美妙JavaScript非同步程式設計
- python 網路程式設計----非阻塞或非同步程式設計Python程式設計非同步
- [譯] 非同步程式設計:阻塞與非阻塞非同步程式設計
- 給程式設計師看的Javascript攻略(完結)- 非同步程式設計師JavaScript非同步
- 向非程式設計師解釋JavaScript程式設計師JavaScript
- 向非程式設計師解釋 JavaScript程式設計師JavaScript
- Javascript中的非同步程式設計JavaScript非同步程式設計
- JavaScript非同步程式設計筆記JavaScript非同步程式設計筆記
- 前端- JavaScript非同步程式設計Promise前端JavaScript非同步程式設計Promise
- 談談 JavaScript 非同步程式設計JavaScript非同步程式設計
- JavaScript 非同步程式設計入門JavaScript非同步程式設計
- 非同步程式設計小結非同步程式設計
- 網路IO之阻塞、非阻塞、同步、非同步總結非同步
- Socket程式設計中的同步、非同步、阻塞和非阻塞(轉)程式設計非同步
- JavaScript非同步程式設計:Generator與AsyncJavaScript非同步程式設計
- JavaScript非同步程式設計-基礎篇JavaScript非同步程式設計
- Javascript非同步程式設計的前世今生JavaScript非同步程式設計
- javascript非同步程式設計(一)-現狀JavaScript非同步程式設計
- JavaScript非同步程式設計助手:Promise模式JavaScript非同步程式設計Promise模式
- JavaScript非同步程式設計的Promise模式JavaScript非同步程式設計Promise模式
- 結對程式設計總結程式設計
- JS非同步程式設計之Promise詳解和使用總結JS非同步程式設計Promise
- iOS多執行緒程式設計:執行緒同步總結iOS執行緒程式設計
- 程式設計技巧總結程式設計
- JavaScript非同步程式設計:非同步的資料收集方法JavaScript非同步程式設計
- 【程式設計素質】程式設計思想總結程式設計
- JavaScript非同步程式設計的6種方法JavaScript非同步程式設計
- javascript 非同步程式設計的5種方式JavaScript非同步程式設計
- Javascript中常見的非同步程式設計模型JavaScript非同步程式設計模型