Node.js中的async?和?await?關(guān)鍵字微任務(wù)和宏任務(wù)
async 和 await 關(guān)鍵字
async 和 await 是 ES2017 中提出來(lái)的,async 和 await 兩個(gè)關(guān)鍵字的出現(xiàn),簡(jiǎn)化的 Promise 的使用。
async 關(guān)鍵字
async關(guān)鍵字使用比較簡(jiǎn)單,所以 async 的使用注意以下三點(diǎn)即可 :
- async 用于修飾一個(gè) function
- async 修飾的函數(shù),總是返回一個(gè) Promise 對(duì)象
- 函數(shù)內(nèi)的所有值,將自動(dòng)包裝在 resolved 的 promise 中
// async?用于修飾一個(gè)?function // 1. async?修飾的函數(shù),總是返回一個(gè)?Promise?對(duì)象 // 2. 函數(shù)的返回值,將自動(dòng)包裝在?resolve?的?promise?中 // 1. async?修飾的函數(shù),總是返回一個(gè)?Promise?對(duì)象 async function fn() { // 2. 函數(shù)的返回值,將自動(dòng)包裝在?resolve?的?promise?中 return '哈哈哈'; } // 以后看一下博客文章之類(lèi)的東西,里面會(huì)有一些變量使用 :foo 和 bar , 無(wú)意義; const foo = fn(); console.log(foo); foo.then(res => { console.log(res); }); // 注意: async修飾的函數(shù)被稱(chēng)為異步函數(shù),可他不是異步執(zhí)行; console.log('我是最后一行代碼');
await關(guān)鍵字
await關(guān)鍵字比較繁瑣,注意點(diǎn)比較多。首先,await 只能出現(xiàn)在 async 函數(shù)內(nèi),await 讓 JS 引擎等待直到promise完成并返回結(jié)果,語(yǔ)法:
let value = await promise對(duì)象; // 等待promise對(duì)象的結(jié)果,然后將結(jié)果賦值給 value
由于await需要等待promise執(zhí)行完畢,所以 await會(huì) 暫停函數(shù)的執(zhí)行,但不會(huì)影響其他同步任務(wù)。
所以,await總結(jié)如下四點(diǎn):
- await只能出現(xiàn)在異步函數(shù)中!
- await能停止代碼執(zhí)行,讓后面的同步代碼,先執(zhí)行;
- await后面跟隨的是一個(gè)promise對(duì)象;
- await返回的是: Promise對(duì)象中的then()中的回調(diào)函數(shù)中的參數(shù)res;
// 定義一個(gè)方法,為的就是返回一個(gè) Promise 對(duì)象,讓下面的await使用; async function getPromise() { return '哈哈哈'; } console.log(1); // 1.await只能出現(xiàn)在async修飾的函數(shù)中! async function fn() { console.log(2); // 2.await后面跟隨的是一個(gè)promise對(duì)象; // 3.await返回的是: Promise對(duì)象中的then()中的回調(diào)函數(shù)中的參數(shù)res; const str = await getPromise(); console.log(str); // 4.await能停止代碼執(zhí)行,讓后面的同步代碼,先執(zhí)行; console.log(3); } // 調(diào)用 fn(); console.log(4); // // 以前用法: // axios().then(res => { // res.data.map() // }); // // 以后用法: // async function name() { // let res = await axios(); // res.data.map(); // }
async 和 await 解決回調(diào)地獄
// async 和 await 解決回調(diào)地獄也要用到 then-fs ,因?yàn)樗苯臃祷?Promise 對(duì)象; ? // 導(dǎo)入 then-fs import thenFs from 'then-fs'; ? // await 一定要出現(xiàn)在異步函數(shù)中 async function fn() { ? ?let str1 = await thenFs.readFile('./txt/a.txt', 'utf8'); ? ?console.log(str1); ? ?let str2 = await thenFs.readFile('./txt/b.txt', 'utf8'); ? ?console.log(str2); ? ?let str3 = await thenFs.readFile('./txt/c.txt', 'utf8'); ? ?console.log(str3); } ? // 調(diào)用函數(shù) fn();
JS執(zhí)行機(jī)制(事件循環(huán))
- js代碼開(kāi)始執(zhí)行后,主線(xiàn)程執(zhí)行棧中會(huì)把任務(wù)分為兩類(lèi).
- 一類(lèi)是同步任務(wù), 一類(lèi)是異步任務(wù); 主線(xiàn)程執(zhí)行棧優(yōu)先執(zhí)行同步任務(wù),
- 異步任務(wù)會(huì)被放入特定的處理程序中,滿(mǎn)足條件后,被放到消息(任務(wù)/事件)隊(duì)列中,
- 主線(xiàn)程執(zhí)行棧中所有的同步任務(wù)執(zhí)行完畢之后,通過(guò)事件循環(huán)去消息(任務(wù)/事件)隊(duì)列中,
- 挑選優(yōu)先滿(mǎn)足條件的程序,放入主線(xiàn)程執(zhí)行棧中執(zhí)行。事件循環(huán),周而復(fù)始,一直執(zhí)行。
微任務(wù)和宏任務(wù)
在ES3 以及以前的版本中,JavaScript本身沒(méi)有發(fā)起異步請(qǐng)求的能力,也就沒(méi)有微任務(wù)的存在。在ES5之后,JavaScript引入了Promise,這樣,不需要瀏覽器,JavaScript引擎自身也能夠發(fā)起異步任務(wù)了。 ? Tick會(huì)觸發(fā)瀏覽器渲染,Promise不會(huì)觸發(fā),所以更加輕量級(jí),多使用;
宏任務(wù)
(macro)task,可以理解是每次執(zhí)行棧執(zhí)行的代碼就是一個(gè)宏任務(wù)
- 主線(xiàn)程上的執(zhí)行棧中所有的代碼塊
- setTimeout
- setInterval
- Ajax
- 事件
微任務(wù)
微任務(wù)(microtask)是宏任務(wù)中的一個(gè)部分,它的執(zhí)行時(shí)機(jī)是在同步代碼執(zhí)行之后,下一個(gè)宏任務(wù)執(zhí)行之前。
總結(jié)起來(lái),微任務(wù)有:
- Promise.then
- process.nextTick(Node.js 環(huán)境)
宏任務(wù)和微任務(wù)執(zhí)行機(jī)制
JS優(yōu)先執(zhí)行同步任務(wù),然后執(zhí)行微任務(wù),最后執(zhí)行宏任務(wù)。
總結(jié):Promise中的then()比大部分異步代碼,優(yōu)先執(zhí)行!
// 結(jié)論: 如果同一時(shí)間既有宏任務(wù)又有微任務(wù)觸發(fā),那么優(yōu)先執(zhí)行微任務(wù); // 宏任務(wù)是宿主發(fā)起的會(huì)觸發(fā)重構(gòu),比較浪費(fèi)資源,后執(zhí)行; // 微任務(wù)是js解釋器發(fā)起的不會(huì)觸發(fā)重構(gòu),比較節(jié)省資源,先執(zhí)行; // 宏任務(wù) setTimeout(() => { //執(zhí)行后 回調(diào)一個(gè)宏事件 console.log('1') }, 0) // 同步代碼 console.log('2'); // 同步代碼 new Promise((resolve) => { console.log('3'); resolve() // 微任務(wù) }).then(() => { console.log('4'); // 微任務(wù) }).then(()=>{ console.log('5') }) // 同步代碼 console.log('6') // 2 3 6 4 5 1
到此這篇關(guān)于Node.js中的async 和 await 關(guān)鍵字微任務(wù)和宏任務(wù)的文章就介紹到這了,更多相關(guān)Node.js async 和 await 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Nodejs Buffer的使用及Stream流和事件機(jī)制詳解
這篇文章主要為大家介紹了Nodejs Buffer的使用及Stream流和事件機(jī)制詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Nodejs 搭建簡(jiǎn)單的Web服務(wù)器詳解及實(shí)例
這篇文章主要介紹了Nodejs 搭建簡(jiǎn)單的Web服務(wù)器詳解及實(shí)例的相關(guān)資料,并附實(shí)例代碼和實(shí)現(xiàn)效果圖,需要的朋友可以參考下2016-11-11nodejs利用ajax實(shí)現(xiàn)網(wǎng)頁(yè)無(wú)刷新上傳圖片實(shí)例代碼
本篇文章主要介紹了nodejs利用ajax實(shí)現(xiàn)網(wǎng)頁(yè)無(wú)刷新上傳圖片實(shí)例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06初學(xué)者如何快速搭建Express開(kāi)發(fā)系統(tǒng)步驟詳解
這篇文章主要介紹了初學(xué)者如何快速搭建Express開(kāi)發(fā)系統(tǒng),結(jié)合實(shí)例形式詳細(xì)分析了express框架搭建的具體步驟與相關(guān)注意事項(xiàng),需要的朋友可以參考下2023-05-05Nodejs小文件拷貝復(fù)制和大文件拷貝復(fù)制方法代碼
NodeJS提供了基本的文件操作API,但是像文件拷貝復(fù)制這種高級(jí)功能就沒(méi)有提供,因此我們先拿文件拷貝程序練手,文件拷貝復(fù)制是在Node.js中常見(jiàn)的操作之一,它允許我們將一個(gè)文件的內(nèi)容復(fù)制到另一個(gè)文件中2023-11-11Nodejs進(jìn)階:如何將圖片轉(zhuǎn)成datauri嵌入到網(wǎng)頁(yè)中去實(shí)例
這篇文章主要介紹了Nodejs進(jìn)階:如何將圖片轉(zhuǎn)成datauri嵌入到網(wǎng)頁(yè)中去,有興趣的可以了解一下。2016-11-11更新npm項(xiàng)目依賴(lài)的實(shí)現(xiàn)方法
依賴(lài)管理是其中一個(gè)至關(guān)重要的環(huán)節(jié),本文主要介紹了更新npm項(xiàng)目依賴(lài)的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06在Node.js下運(yùn)用MQTT協(xié)議實(shí)現(xiàn)即時(shí)通訊及離線(xiàn)推送的方法
這篇文章主要介紹了在Node.js下運(yùn)用MQTT協(xié)議實(shí)現(xiàn)即時(shí)通訊及離線(xiàn)推送的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01express框架實(shí)現(xiàn)基于Websocket建立的簡(jiǎn)易聊天室
本篇文章主要介紹了express框架實(shí)現(xiàn)基于Websocket建立的簡(jiǎn)易聊天室,具有一定的參考價(jià)值,有興趣的可以了解一下2017-08-08