Promise 必知必會(huì)(十道題)

Promise 想必大家都十分熟悉鞍爱,想想就那么幾個(gè) api涕蜂,可是你真的了解 Promise 嗎析校?本文根據(jù) Promise 的一些知識(shí)點(diǎn)總結(jié)了十道題礁哄,看看你能做對(duì)幾道长酗。

以下 promise 均指代 Promise 實(shí)例,環(huán)境是 Node.js桐绒。

題目一

const promise = new Promise((resolve, reject) => {
    console.log(1)
    resolve()
    console.log(2)
})
promise.then(() => {
    console.log(3)
})
console.log(4)

運(yùn)行結(jié)果:

1
2
4
3

解釋:Promise 構(gòu)造函數(shù)是同步執(zhí)行的夺脾,promise.then 中的函數(shù)是異步執(zhí)行的。

題目二

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  }, 1000)
})
const promise2 = promise1.then(() => {
  throw new Error('error!!!')
})

console.log('promise1', promise1)
console.log('promise2', promise2)

setTimeout(() => {
  console.log('promise1', promise1)
  console.log('promise2', promise2)
}, 2000)

運(yùn)行結(jié)果:

promise1 Promise { <pending> }
promise2 Promise { <pending> }
(node:50928) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: error!!!
(node:50928) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
promise1 Promise { 'success' }
promise2 Promise {
  <rejected> Error: error!!!
    at promise.then (...)
    at <anonymous> }

解釋:promise 有 3 種狀態(tài):pending茉继、fulfilled 或 rejected咧叭。狀態(tài)改變只能是 pending->fulfilled 或者 pending->rejected,狀態(tài)一旦改變則不能再變烁竭。上面 promise2 并不是 promise1菲茬,而是返回的一個(gè)新的 Promise 實(shí)例。

題目三

const promise = new Promise((resolve, reject) => {
  resolve('success1')
  reject('error')
  resolve('success2')
})

promise
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

運(yùn)行結(jié)果:

then: success1

解釋:構(gòu)造函數(shù)中的 resolve 或 reject 只有第一次執(zhí)行有效派撕,多次調(diào)用沒(méi)有任何作用婉弹,呼應(yīng)代碼二結(jié)論:promise 狀態(tài)一旦改變則不能再變。

題目四

Promise.resolve(1)
  .then((res) => {
    console.log(res)
    return 2
  })
  .catch((err) => {
    return 3
  })
  .then((res) => {
    console.log(res)
  })

運(yùn)行結(jié)果:

1
2

解釋:promise 可以鏈?zhǔn)秸{(diào)用终吼。提起鏈?zhǔn)秸{(diào)用我們通常會(huì)想到通過(guò) return this 實(shí)現(xiàn)镀赌,不過(guò) Promise 并不是這樣實(shí)現(xiàn)的。promise 每次調(diào)用 .then 或者 .catch 都會(huì)返回一個(gè)新的 promise际跪,從而實(shí)現(xiàn)了鏈?zhǔn)秸{(diào)用商佛。

題目五

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    console.log('once')
    resolve('success')
  }, 1000)
})

const start = Date.now()
promise.then((res) => {
  console.log(res, Date.now() - start)
})
promise.then((res) => {
  console.log(res, Date.now() - start)
})

運(yùn)行結(jié)果:

once
success 1005
success 1007

解釋:promise 的 .then 或者 .catch 可以被調(diào)用多次,但這里 Promise 構(gòu)造函數(shù)只執(zhí)行一次垫卤⊥茫或者說(shuō) promise 內(nèi)部狀態(tài)一經(jīng)改變,并且有了一個(gè)值穴肘,那么后續(xù)每次調(diào)用 .then 或者 .catch 都會(huì)直接拿到該值歇盼。

題目六

Promise.resolve()
  .then(() => {
    return new Error('error!!!')
  })
  .then((res) => {
    console.log('then: ', res)
  })
  .catch((err) => {
    console.log('catch: ', err)
  })

運(yùn)行結(jié)果:

then: Error: error!!!
    at Promise.resolve.then (...)
    at ...

解釋:.then 或者 .catch 中 return 一個(gè) error 對(duì)象并不會(huì)拋出錯(cuò)誤,所以不會(huì)被后續(xù)的 .catch 捕獲评抚,需要改成其中一種:

return Promise.reject(new Error('error!!!'))
throw new Error('error!!!')

因?yàn)榉祷厝我庖粋€(gè)非 promise 的值都會(huì)被包裹成 promise 對(duì)象豹缀,即 return new Error('error!!!') 等價(jià)于 return Promise.resolve(new Error('error!!!'))伯复。

題目七

const promise = Promise.resolve()
  .then(() => {
    return promise
  })
promise.catch(console.error)

運(yùn)行結(jié)果:

TypeError: Chaining cycle detected for promise #<Promise>
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)
    at Function.Module.runMain (module.js:667:11)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:607:3

解釋:.then 或 .catch 返回的值不能是 promise 本身,否則會(huì)造成死循環(huán)邢笙。類似于:

process.nextTick(function tick () {
  console.log('tick')
  process.nextTick(tick)
})

題目八

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)

運(yùn)行結(jié)果:

1

解釋:.then 或者 .catch 的參數(shù)期望是函數(shù)啸如,傳入非函數(shù)則會(huì)發(fā)生值穿透。

題目九

Promise.resolve()
  .then(function success (res) {
    throw new Error('error')
  }, function fail1 (e) {
    console.error('fail1: ', e)
  })
  .catch(function fail2 (e) {
    console.error('fail2: ', e)
  })

運(yùn)行結(jié)果:

fail2: Error: error
    at success (...)
    at ...

解釋:.then 可以接收兩個(gè)參數(shù)氮惯,第一個(gè)是處理成功的函數(shù)叮雳,第二個(gè)是處理錯(cuò)誤的函數(shù)。.catch 是 .then 第二個(gè)參數(shù)的簡(jiǎn)便寫(xiě)法妇汗,但是它們用法上有一點(diǎn)需要注意:.then 的第二個(gè)處理錯(cuò)誤的函數(shù)捕獲不了第一個(gè)處理成功的函數(shù)拋出的錯(cuò)誤帘不,而后續(xù)的 .catch 可以捕獲之前的錯(cuò)誤。當(dāng)然以下代碼也可以:

Promise.resolve()
  .then(function success1 (res) {
    throw new Error('error')
  }, function fail1 (e) {
    console.error('fail1: ', e)
  })
  .then(function success2 (res) {
  }, function fail2 (e) {
    console.error('fail2: ', e)
  })

題目十

process.nextTick(() => {
  console.log('nextTick')
})
Promise.resolve()
  .then(() => {
    console.log('then')
  })
setImmediate(() => {
  console.log('setImmediate')
})
console.log('end')

運(yùn)行結(jié)果:

end
nextTick
then
setImmediate

解釋:process.nextTick 和 promise.then 都屬于 microtask杨箭,而 setImmediate 屬于 macrotask寞焙,在事件循環(huán)的 check 階段執(zhí)行。事件循環(huán)的每個(gè)階段(macrotask)之間都會(huì)執(zhí)行 microtask互婿,事件循環(huán)的開(kāi)始會(huì)先執(zhí)行一次 microtask捣郊。

******轉(zhuǎn)自******

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市慈参,隨后出現(xiàn)的幾起案子呛牲,更是在濱河造成了極大的恐慌,老刑警劉巖懂牧,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侈净,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡僧凤,警方通過(guò)查閱死者的電腦和手機(jī)畜侦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)躯保,“玉大人旋膳,你說(shuō)我怎么就攤上這事⊥臼拢” “怎么了验懊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)尸变。 經(jīng)常有香客問(wèn)我义图,道長(zhǎng),這世上最難降的妖魔是什么召烂? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任碱工,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘怕篷。我一直安慰自己历筝,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布廊谓。 她就那樣靜靜地躺著梳猪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蒸痹。 梳的紋絲不亂的頭發(fā)上春弥,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音电抚,去河邊找鬼惕稻。 笑死竖共,一個(gè)胖子當(dāng)著我的面吹牛蝙叛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播公给,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼借帘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了淌铐?” 一聲冷哼從身側(cè)響起肺然,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎腿准,沒(méi)想到半個(gè)月后际起,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吐葱,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年街望,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弟跑。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡灾前,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出孟辑,到底是詐尸還是另有隱情哎甲,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布饲嗽,位于F島的核電站炭玫,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏貌虾。R本人自食惡果不足惜吞加,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧榴鼎,春花似錦伯诬、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至平项,卻和暖如春赫舒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背闽瓢。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工接癌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人扣讼。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓横浑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親消玄。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贸诚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 姚麗冰 學(xué)號(hào):16050120089 原文鏈接 zhuanlan.zhihu.com 【嵌牛導(dǎo)讀】Promise...
    小犽閱讀 480評(píng)論 0 0
  • 本文適用的讀者 本文寫(xiě)給有一定Promise使用經(jīng)驗(yàn)的人,如果你還沒(méi)有使用過(guò)Promise销钝,這篇文章可能不適合你有咨,...
    HZ充電大喵閱讀 7,311評(píng)論 6 19
  • 編后吐槽:寫(xiě)的快花眼,很詳細(xì)蒸健,耐心看必受益匪淺 JavaScript的執(zhí)行環(huán)境是「單線程」的座享。所謂單線程,是指JS...
    果汁涼茶丶閱讀 4,633評(píng)論 8 27
  • 00、前言Promise 是異步編程的一種解決方案橡娄,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大诗箍。它由社區(qū)...
    夜幕小草閱讀 2,133評(píng)論 0 12
  • Promiese 簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果挽唉,語(yǔ)法上說(shuō)滤祖,Pr...
    雨飛飛雨閱讀 3,360評(píng)論 0 19