ES6 Promise 的這部分,起初我看《 JavaScript 高級(jí)程序設(shè)計(jì) 》4th 的時(shí)候看得云里霧里,說(shuō)實(shí)話我不知道是不是因?yàn)樵摃?shū)第 4 版中文版的質(zhì)量有所下降,講得沒(méi)那么清晰透徹了。后來(lái)我找到阮一峰老師的《 ES6 標(biāo)準(zhǔn)入門(mén)》重看了這部分,《 ES6 標(biāo)準(zhǔn)入門(mén) 》中的 Promise 這部分很合我的胃口,其中舉的例子是真的好。PS:但《 ES6 標(biāo)準(zhǔn)入門(mén) 》我也認(rèn)為有個(gè)小缺點(diǎn)——重點(diǎn)知識(shí)沒(méi)有加粗(或者其他標(biāo)記或者標(biāo)記的重點(diǎn)較少),你必須仔細(xì)的看每一句話,不然你可能錯(cuò)過(guò)一個(gè)很重要的知識(shí),或許該書(shū)是全程干貨?
雖然我說(shuō)是新手向,但我不想廢話,所以本文還是假設(shè)你在其他地方看過(guò) Promise 的內(nèi)容,只是感覺(jué)沒(méi)理解。或者其實(shí)這篇博客我只是想總結(jié)給我自己看?
構(gòu)造函數(shù)
-
Promise 構(gòu)造函數(shù)接受一個(gè)執(zhí)行器(executor)函數(shù)作為參數(shù)。這個(gè)參數(shù)是必選的。
let p = new Promise(() => {});
這里給了一個(gè)空函數(shù)作為執(zhí)行器函數(shù)也是可以的。
-
這個(gè)執(zhí)行器函數(shù)什么時(shí)候開(kāi)始執(zhí)行呢?它是異步執(zhí)行的嗎?
let p = new Promise((resolve,reject) => { console.log('1: 這里是執(zhí)行器函數(shù)啦'); }); console.log('2: Promise 實(shí)例化之后'); console.log('3:', p); // 輸出 // 1: 這里是執(zhí)行器函數(shù)啦 // 2: Promise 實(shí)例化之后 // 3: Promise { <pending> }
所以我的結(jié)論是:執(zhí)行器函數(shù)在實(shí)例化 Promise 時(shí)會(huì)被同步調(diào)用。
我沒(méi)看源碼哈,我猜 Promise 構(gòu)造函數(shù)大概長(zhǎng)這樣:function Promise(executor) { ...// 略去一萬(wàn)行~ executor(resolve, reject); ...// 略 }
等我看了源碼回來(lái)填坑。
-
執(zhí)行器函數(shù)的參數(shù) resolve 和 reject。這兩個(gè)參數(shù)很重要,關(guān)系到 Promise 的機(jī)制。
- Promise 實(shí)例有三種可能的狀態(tài):pending(待定)、fulfilled(兌現(xiàn),有時(shí)候也稱為“解決”,resolved)、rejected(拒絕)。注意:瀏覽器控制臺(tái)才能打印出 Promise 實(shí)例的狀態(tài)。
- 執(zhí)行器函數(shù)的兩個(gè)參數(shù) resolve 和 reject 是兩個(gè)函數(shù),由 JS 引擎提供,不用自己部署。你也無(wú)法自己定義 resolve 和 reject。
這樣寫(xiě)很清晰了吧,這里自己定義的 myExecutor 中的參數(shù) resolve 和 reject 都是形參(你想怎么命名都可以哦),myExecutor 調(diào)用是由 JS 引擎完成的,所以實(shí)參只能由 JS 引擎給。稍微完善一下猜測(cè)的 Promise 構(gòu)造函數(shù):function myExecutor(resolve, reject) { console.log('這里是執(zhí)行器,over'); } let p = new Promise(myExecutor); // 這里是執(zhí)行器,over
function Promise(executor) { ...// 略去一萬(wàn)行~ let resolve = function () { ...// 這里便是 JS 引擎定義的 resolve 函數(shù) } let reject = function () { ...// 這里便是 JS 引擎定義的 reject 函數(shù) } executor(resolve, reject); ...// 略 }
- pending(待定)是 Promise 實(shí)例的最初始狀態(tài)。在執(zhí)行器函數(shù)中調(diào)用 resolve() 會(huì)把 Promise 實(shí)例狀態(tài)切換為 fulfilled(解決),調(diào)用 reject() 會(huì)把狀態(tài)切換為 rejected(拒絕)。另外,調(diào)用 reject() 也會(huì)拋出錯(cuò)誤
let p = new Promise((resolve,reject) => { console.log('1: 這里是執(zhí)行器函數(shù)啦'); // 執(zhí)行器函數(shù)中調(diào)用 resolve resolve(); }); console.log('2: Promise 實(shí)例化之后'); console.log('3:', p); // 1: 這里是執(zhí)行器函數(shù)啦 // 2: Promise 實(shí)例化之后 // 3: Promise {<fulfilled>: undefined}
let p = new Promise((resolve,reject) => { console.log('1: 這里是執(zhí)行器函數(shù)啦'); // 執(zhí)行器函數(shù)中調(diào)用 reject reject(); }); console.log('2: Promise 實(shí)例化之后'); console.log('3:', p); // 1: 這里是執(zhí)行器函數(shù)啦 // 2: Promise 實(shí)例化之后 // 3: Promise {<rejected>: undefined} // 這里還有個(gè) error : Uncaught (in promise) undefined
-
為什么說(shuō) Promise 是目前主導(dǎo)性的異步編程機(jī)制?前面的例子中都沒(méi)有出現(xiàn)異步操作。執(zhí)行器函數(shù)是同步執(zhí)行的,那么 Promise 的異步在哪?
- 雖然執(zhí)行器函數(shù)是同步執(zhí)行的,但是可以用執(zhí)行器函數(shù)把異步操作包裹起來(lái)。比如在執(zhí)行器函數(shù)中調(diào)用 setTimeout()。
這里有 2 和 5 兩個(gè)異步操作。let p = new Promise((resolve,reject) => { console.log('1'); setTimeout(console.log, 0, '2'); console.log('3'); }); console.log('4', p); setTimeout(console.log, 0, '5', p); // 1 // 3 // 4 Promise { <pending> } // 2 // 5 Promise { <pending> }
- 雖然執(zhí)行器函數(shù)是同步執(zhí)行的,但是可以用執(zhí)行器函數(shù)把異步操作包裹起來(lái)。比如在執(zhí)行器函數(shù)中調(diào)用 setTimeout()。
then 方法
- 執(zhí)行器函數(shù)中的異步操作觸發(fā) Promise 本身的異步。then 定義了 Promise 的狀態(tài)變?yōu)?fulfilled 或 rejected 時(shí)的回調(diào)函數(shù),這就是 Promise 本身的異步。執(zhí)行器函數(shù)中執(zhí)行的異步操作異步改變 Promise 實(shí)例的狀態(tài)時(shí),便觸發(fā)了 Promise 的異步。Promise 居然是微任務(wù),,,,,,我的理解要推翻重新理解了。。。。。
先寫(xiě)到這,待續(xù)