先說一下微任務:
微任務佇列:
異步任務需要適當的管理,為此,ECMA 標準規定了一個內部佇列
PromiseJobs,通常被稱為“微任務佇列(microtask queue)”(ES8 術語)
佇列(queue)是先進先出的:首先進入佇列的任務會首先運行,
只有在 JavaScript 引擎中沒有其它任務在運行時,才開始執行任務佇列中的任務,
https://zh.javascript.info/microtask-queue
“任務佇列"是一個事件的佇列(也可以理解成訊息的佇列),IO設備完成一項任務,就在"任務佇列"中添加一個事件,表示相關的異步任務可以進入"執行堆疊"了,主執行緒讀取"任務佇列”,就是讀取里面有哪些事件,https://www.ruanyifeng.com/blog/2014/10/event-loop.html
? ——阮一峰
我的理解:微任務佇列其實就是一些事件的傀儡佇列,這個傀儡就是回呼函式,當主執行緒任務完成之后,開始讀取微任務佇列中的事件時,就是去執行事件對應的回呼函式,
ps:(可以想象成一個作業狂,他會提前準備一個框框(微任務佇列)放一些當前任務中可以慢慢處理的其他任務,然后先去做他當前的主要的作業,做完主要作業就回去檢查這個框框,這個框的任務也做完了,就去問老大(宏任務佇列)還有沒有下一個任務(下一個宏任務))
微任務中也可以有微任務,所以會有無限套娃的風險,https://developer.mozilla.org/zh-CN/docs/Web/API/HTML_DOM_API/Microtask_guide
promise中的then方法:

-
明確then的回呼函式是什么時候進入微任務佇列的
思否:https://segmentfault.com/q/1010000022578087
我覺得這個答案更符合我的理解:
then的回呼函式什么時候進入PromiseJobs取決于then方法前一個promise的狀態,
如果呼叫 then 時 promise 是 pending 狀態,回呼會進入 promise 的 [[PromiseFulfill/RejectReactions]] 串列里;否則會進入 PromiseJobs,
看例子:
eg1(呼叫then的promise狀態為pending):
new Promise(()=>{}).then((res)=>{console.log("我是then"+res)})
console.log("我是同步的")
輸出:
"我是同步的"
結論:如果呼叫 then 時 promise 是 pending 狀態,回呼會進入 promise 的[[PromiseFulfill/RejectReactions]] 串列里等待執行;
eg2(呼叫then的promise狀態不為pending):
new Promise((res)=>{res(1)}).then((res)=>{console.log("我是then:"+res)})
console.log("我是同步的")
輸出:
"我是同步的"
"我是then:1"
結論:
如果呼叫 then 時 promise 不是 pending 狀態,則會進入 PromiseJobs,待同步任務執行完,則執行PromiseJobs中的任務
eg3:
new Promise((res)=>{}).then(console.log("我是then"))
console.log("我是同步的")
輸出:
"我是then"
"我是同步的"
思考:呼叫then的promise是pending狀態,為什么"我是then"還是會列印?👇
eg4:
new Promise((res)=>{res(1)}).then(console.log("我是then"))
console.log("我是同步的")
輸出:
"我是then"
"我是同步的"
思考:????為什么還是會列印👇
👇👇👇
-
then方法的引數
then方法接受兩個引數(onFulfilled, onRejected)
-
If
onFulfilledis not a function, it must be ignored. -
If
onRejectedis not a function, it must be ignored.? 檔案——https://promisesaplus.com/
上面說的很清楚,如果接受的引數不是一個函式,那么必須被忽略(不管他)所以會有值穿透的情況
好,再來看看上面的思考:
new Promise(()=>{}).then(console.log("我是then")) console.log("我是同步的") 首先明確一點:console.log是一個方法,也就是一個函式,所以你再看看你then里面傳的是什么,是console.log("xxxxxx"),所以你在這里同步立即執行這個函式,然后把這個函式的回傳值傳到then里面去,所以相當于你在then里面傳了一個值undefined 不信,我們來看看: new Promise((res)=>{res(1)}).then(console.log("我是then")) console.log("我是同步的") 這個輸出和上面一樣,但是不一樣的是,呼叫then的promise有結果 1 ,且狀態不是pending 所以就算中間的then會被忽略,再呼叫一個正常then還是可以接受到資料 new Promise((res)=>{res(1)}) .then(console.log("我是then")) .then(res=>{console.log("promise的結果:"+res)}) console.log("我是同步的") 輸出: "我是then" "我是同步的" "promise的結果:1" 不信再來: new Promise(()=>{}) .then((function(){console.log(2)})())//中間這個then傳入一個立即執行的函式效果和上面一樣 .then(res=>{console.log(res)}) console.log("我是同步的") 輸出: 2 "我是同步的" 好了,到了這里應該都明白了,接下來,看一下then添加回呼函式的寫法:https://wangdoc.com/javascript/async/promise.html#promiseprototypethenlet func = function() { return new Promise((resolve, reject) => { resolve('我是老大new Promise'); }); }; let cb = function() { return '我是回呼函式的回傳值'; } // 1. func().then(function () { return cb();//這一句等同于 return '我是回呼函式的回傳值' }).then(resp => { console.warn(resp); // 輸出 '我是回呼函式的回傳值' console.warn('1 =========<'); }); // 2. func().then(function () { cb();//在這個函式里面只是執行了一下cb函式,但是沒有回傳任何東西:所以默認回傳undefined return undefined }).then(resp => { console.warn(resp);// 輸出: undefined console.warn('2 =========<'); }); // 3. func() .then(cb())// 這個then里面傳入的相當于是cb函式的回傳值 '我是回呼函式的回傳值',所以發生值穿透 .then(resp => { console.warn(resp); // 值穿透 ——> 輸出:'我是老大new Promise' console.warn('3 =========<'); }); // 4. func().then(cb)// 這里的then里面傳入的是一個函式,而不是一個值,所以內部會對這個函式進行一個封裝,回傳'我是回呼函式的回傳值' .then(resp => { console.warn(resp); //輸出:'我是回呼函式的回傳值' console.warn('4 =========<'); }); 內部封裝大致如下:👇👇.then(new Promise((res,rej)=>{ res(cb()); })) -


console.log()和console.log是不一樣的
then方法內部會進行一個判斷:看是否是函式
-
當then里面傳入console.log時,相當于傳入了一個函式log,于是promise的函式執行器就會幫你呼叫new Promise(),去呼叫這個函式,
傳入console.log時,在then中相當于發生如下程序 new Promise(res=>res(1)).then(()=>{ return new Promise((res,rej)=>{ res(console.log()); }) }) -
當then里面傳入console.log()時,相當于傳入了一個非函式,也就是console.log()這個函式的回傳值undefined,所以會發生值穿透,所以上面第二種情況,先列印2,再列印new Promise中的res的引數值

- then的回呼方法的注冊時機(事件機制是先注冊再執行)
注冊時機其實還是看呼叫then的promise狀態,只要promise狀態改變了,其呼叫的then的方法就會被注冊,但是還沒有被執,執行再按照注冊順序進行
https://juejin.cn/post/6844903987183894535
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/374791.html
標籤:其他
