javascript
jsp循环输出表格_「翻译」JS可视化学习之七:Promise、事件循环和异步2
喜歡排隊(duì)吧,它能保護(hù)你的時(shí)間和精力 - 排隊(duì)紀(jì)律維護(hù)員Event Loop
Promise和事件循環(huán)概覽圖
請(qǐng)注意上面這張圖,Promise和事件循環(huán)的那些事,將在這個(gè)圖上緩緩展開(kāi)。
微任務(wù)和(宏)任務(wù)
好了,(經(jīng)過(guò)上一節(jié)對(duì)Promise的理解)現(xiàn)在我們對(duì)如何創(chuàng)建Promise以及如何從Promise中獲取值多了一些了解。讓我們?cè)?strong>script中添加更多的代碼,然后再次運(yùn)行它:
等等,發(fā)生了什么?!
首先,輸出了"Start!"。好吧,顯而易見(jiàn)的:console.log('Start!') 就在第一行!但是,輸出的第二個(gè)值是"End!"而不是Promise的值!只有在"End!"輸出后,Promise的值才被輸出。這是怎么回事?
我們終于見(jiàn)識(shí)到Promise的真正力量!雖然JavaScript是單線程的,但是我們可以使用Promise添加異步行為!
但是稍等一下,我們以前不是見(jiàn)過(guò)了嗎?在JavaScript事件循環(huán)中(「翻譯」JavaScript的可視化學(xué)習(xí)之一:事件循環(huán)),我們不也可以使用瀏覽器的本地方法(如setTimeout)來(lái)創(chuàng)建某種異步行為嗎?
沒(méi)錯(cuò)!但是,在事件循環(huán)中,實(shí)際上有兩種類(lèi)型的隊(duì)列:(宏)任務(wù)隊(duì)列(或簡(jiǎn)稱(chēng)為任務(wù)隊(duì)列):(macro) task queue 和微任務(wù)隊(duì)列:microtask queue。(宏)任務(wù)隊(duì)列用于(宏)任務(wù),微任務(wù)隊(duì)列用于微任務(wù)。
那么什么是(宏)任務(wù),什么是微任務(wù)呢?下面表格羅列了一些最常用的!
(Macro)task:
setTimeout
setInterval
setImmediate
Microtask:
process.nextTick
Promise callback
queueMicrotask
啊,我們?cè)谖⑷蝿?wù)列表中看到了Promise!當(dāng)Promise處理并調(diào)用其then()、catch()或finally()方法時(shí),該方法內(nèi)的回調(diào)將添加到微任務(wù)隊(duì)列中!這意味著then()、catch()或finally()方法中的回調(diào)不會(huì)立即執(zhí)行,這實(shí)際上是在我們的JavaScript代碼中添加了一些異步行為!
那么then()、catch()或finally()回調(diào)函數(shù)在什么時(shí)候執(zhí)行呢?事件循環(huán)為任務(wù)設(shè)定了不同的優(yōu)先級(jí):
1、當(dāng)前在調(diào)用堆棧中的所有函數(shù)被執(zhí)行,當(dāng)它們返回一個(gè)值時(shí),它們將從堆棧中彈出。
2、當(dāng)調(diào)用堆棧為空時(shí),所有排隊(duì)的微任務(wù)將一個(gè)接一個(gè)的彈出到調(diào)用堆棧中,并執(zhí)行!(微任務(wù)本身也可以返回新的微任務(wù),實(shí)際創(chuàng)建了一個(gè)無(wú)限的微任務(wù)循環(huán))
3、如果調(diào)用堆棧和微任務(wù)隊(duì)列都為空,則事件循環(huán)將檢查(宏)任務(wù)隊(duì)列中是否還有任務(wù)。如果有,任務(wù)被彈出到調(diào)用堆棧,執(zhí)行,然后彈出調(diào)用堆棧!
讓我們看一個(gè)簡(jiǎn)單的例子,簡(jiǎn)單地使用:
Task1: 一個(gè)立即添加到調(diào)用堆棧中的函數(shù),例如在代碼中立即調(diào)用它。
Task2, Task3, Task4: 微任務(wù),例如一個(gè)Promise的then回調(diào),或使用queueMicrotask添加的任務(wù)。
Task5, Task6: (宏)任務(wù),例如setTimeout或setImmediate回調(diào)。
首先,Task1返回一個(gè)值并從調(diào)用堆棧中彈出。然后,引擎檢查微任務(wù)隊(duì)列中排隊(duì)的任務(wù)。一旦所有任務(wù)都被放入調(diào)用堆棧并最終彈出,引擎將檢查(宏)任務(wù)隊(duì)列中的任務(wù),任務(wù)將彈出到調(diào)用堆棧中,并在它們返回值時(shí)彈出。
好吧,好吧,粉色盒子夠多了。讓我們用一些真正的代碼來(lái)使用它!
console.log('Start!')setTimeout(() => {console.log('Timeout!')}, 0)Promise.resolve('Promise').then(res => console.log(res))console.log('End!')在這段代碼中,我們有宏任務(wù)setTimeout和微任務(wù)Promise的 then()回調(diào)。定位到setTimeout函數(shù)的行,讓我們一步一步地運(yùn)行這段代碼,看看會(huì)輸出了什么!
小提示 - 在下面的示例中,我展示了如下方法console.log,setTimeout和Promise.resolve,他們被添加到調(diào)用堆棧中。它們是內(nèi)部方法,實(shí)際上不會(huì)出現(xiàn)在堆棧跟蹤中 — 因此,如果您正在使用調(diào)試器并且在任何地方都看不到它們,請(qǐng)不要擔(dān)心!這么做只是為了讓解釋這個(gè)概念更容易,而不需要添加一堆示例代碼。
在第一行,引擎遇到console.log()方法。它被添加到調(diào)用堆棧中,然后輸出"Start!"到控制臺(tái)。方法從調(diào)用堆棧中彈出,引擎繼續(xù)運(yùn)行。
引擎遇到setTimeout方法,該方法被彈出到調(diào)用堆棧中。setTimeout方法是瀏覽器的本地方法:它的回調(diào)函數(shù)(() => console.log('In timeout')) 將被添加到Web API中,直到計(jì)時(shí)器完成。雖然我們?yōu)橛?jì)時(shí)器提供了值 0,但是回調(diào)仍然會(huì)首先被推送到Web API,之后它會(huì)被添加到(宏)任務(wù)隊(duì)列中:setTimeout是一個(gè)宏任務(wù)!
引擎遇到Promise.resolve()方法。這個(gè)Promise.resolve()方法被添加到調(diào)用堆棧中,之后處理并返回"Promise!"。然后它的then回調(diào)函數(shù)被添加到微任務(wù)隊(duì)列中。
引擎遇到console.log()方法。它會(huì)立即添加到調(diào)用堆棧中,然后輸出"End!"到控制臺(tái),從調(diào)用堆棧中彈出,引擎繼續(xù)運(yùn)行。
引擎發(fā)現(xiàn)調(diào)用堆棧現(xiàn)在是空的。由于調(diào)用堆棧是空的,它將檢查微任務(wù)隊(duì)列中是否有排隊(duì)的任務(wù)!是的,Promise的then回調(diào)正在等待!它被彈出到調(diào)用堆棧中,然后輸出Promise的值:在這里是字符串"promise!"。
引擎發(fā)現(xiàn)調(diào)用堆棧是空的,因此它將再次檢查微任務(wù)隊(duì)列,以查看是否有排隊(duì)的任務(wù)。不,微任務(wù)隊(duì)列都是空的。
是時(shí)候檢查(宏)任務(wù)隊(duì)列了:setTimeout回調(diào)仍在那里等待!setTimeout回調(diào)被彈出到調(diào)用堆棧。回調(diào)函數(shù)返回console.log方法,該方法輸出字符串“In timeout!”。setTimeout回調(diào)從調(diào)用堆棧中彈出。
終于,一切都完成了!現(xiàn)在看來(lái)我們之前看到的輸出結(jié)果并不是那么出乎意料。
翻譯來(lái)源:https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke
總結(jié)
以上是生活随笔為你收集整理的jsp循环输出表格_「翻译」JS可视化学习之七:Promise、事件循环和异步2的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux的yum源怎么配(linux的
- 下一篇: 可为空的对象必须具有一个值_前端:这里有