午夜剧场伦理_日本一道高清_国产又黄又硬_91黄色网战_女同久久另类69精品国产_妹妹的朋友在线

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

JS異步代碼單元測(cè)試之神奇的Promise

瀏覽:191日期:2024-03-27 15:02:46
前言

寫(xiě)這篇文章的起因是在寫(xiě)單元測(cè)試時(shí),做形如下測(cè)試時(shí)

new Promise((resolve, reject) => reject(1)).then().catch(err => { console.log(err)})async function jestTest () { await Promise.resolve().then() console.log(’這個(gè)時(shí)候catch預(yù)期已經(jīng)被調(diào)用,且輸出日志’)}jestTest()

無(wú)法使用await將測(cè)試代碼恰好阻塞到catch在Event Loop中被調(diào)用后的時(shí)機(jī),從而檢測(cè)到catch的執(zhí)行,通過(guò)測(cè)試。

而使用“神奇”一詞則是因?yàn)?promsie 的鏈?zhǔn)秸{(diào)用中確實(shí)有很多默認(rèn)的 handler 和值的隱含傳遞。

promise 的鏈?zhǔn)秸{(diào)用

為了不浪費(fèi)大家的時(shí)間,我們先看一個(gè)例子:

Promise.resolve(’promise1’).then(res => { console.log(’promise1-1 then’)}).then(res => { console.log(’promise1-2 then’)}).then(res => { console.log(’promise1-3 then’)}).then(res => { console.log(’promise1-4 then’)})Promise.resolve(’promise2’).then(res => { console.log(’promise2-1 then’) throw new Error(’mock error 1’)}).then(res => { console.log(’promise2-2 then’) throw new Error(’mock error 2’)}).catch(err => { console.log(err)})

如果你答出的上述代碼的輸出順序與下述相同,那么你可以跳過(guò)這篇文章:

promise1-1 then

promise2-1 then

promise1-2 then

promise1-3 then

Error: mock error 1

promise1-4 then

首先有一個(gè)前提,就是你已經(jīng)知道了,這兩個(gè) promise 的 then 的調(diào)用是交叉入棧的(從頭三行輸出也能看出來(lái)),如果不清楚這部分內(nèi)容,可以查閱 Event Loop 的相關(guān)文章,同時(shí)需要注意的是,在文章所指明的版本中 Chrome 與 NodejsEvent Loop 機(jī)制已經(jīng)相同。

MDN 的錯(cuò)誤

我們?nèi)シ喯略荆ㄎ易隽诵薷模?MDN 關(guān)于 catch 的一段描述:

Basically, a promise chain stops if there’s an exception, looking down the chain for catch handlers instead.

鏈?zhǔn)秸{(diào)用在發(fā)生異常時(shí)會(huì)停止,在鏈上查找 catch 語(yǔ)句來(lái)執(zhí)行。

我最初的誤解與此相同,誤以為 catch 會(huì)直接抓到第一個(gè)throw Error,即Error會(huì)在promise1-2之后輸出,即promise2-2所在的then并不會(huì)被加入調(diào)用棧。

而通過(guò)觀(guān)察實(shí)際的輸出結(jié)果發(fā)現(xiàn)并非如此,那么可以說(shuō)明 MDN 解釋的字面意思應(yīng)該是錯(cuò)的,鏈?zhǔn)秸{(diào)用并沒(méi)有停止,而是執(zhí)行了我們沒(méi)看到的東西。

鏈?zhǔn)降哪J(rèn)處理

這時(shí)我們需要知道then的一個(gè)默認(rèn)處理,同樣直接引用 MDN 的描述:

If the Promise that then is called on adopts a state (fulfillment or rejection) for which then has no handler, a new Promise is created with no additional handlers, simply adopting the final state of the original Promise on which then was called.

如果你的 promise 的 then 缺少了對(duì)應(yīng)狀態(tài)處理的回調(diào),那么 then 會(huì)自動(dòng)生成一個(gè)接受此 promise 狀態(tài)的 promise,即 then 會(huì)返回一個(gè)狀態(tài)引用相同的 promsie,交給后續(xù)的調(diào)用。

那么上述代碼中的第二個(gè) promise 部分就等效于

Promise.resolve(’promise2’).then(res => { console.log(’promise2-1 then’) throw new Error(’mock error 1’)}).then(res => { console.log(’promise2-2 then’) throw new Error(’mock error 2’)// 注意這個(gè) onRejected}, (err) => { return Promise.reject(err)}).catch(err => { console.log(err)})

也就是說(shuō)在輸出結(jié)果的promise1-2和promise1-3之間是執(zhí)行了promise2-2所在的then的,也就是說(shuō)鏈?zhǔn)秸{(diào)用并沒(méi)有直接停止,promise2-2所在的then還是被加入了調(diào)用棧。而catch并不是直接catch的第一個(gè)then拋出的錯(cuò)誤,而是這個(gè)隱藏的onRejected返回的同樣狀態(tài)的promise。

簡(jiǎn)寫(xiě)

同理我們需要知道的是,catch(onRejected)是then(undefined, onRejected)的簡(jiǎn)寫(xiě),即就算調(diào)用鏈的前置調(diào)用沒(méi)有發(fā)生錯(cuò)誤,catch也是會(huì)進(jìn)入調(diào)用棧而非直接跳過(guò)的。

Promise.resolve(’promise1’).then(res => { console.log(’promise1-1 then’)}).then(res => { console.log(’promise1-2 then’)}).then(res => { console.log(’promise1-3 then’)})Promise.resolve(’promise2’).then(res => { console.log(’promise2-1 then’)}).catch(err => { console.log(err)}).then(res => { console.log(’其實(shí)我是 promise2-3 then’)})async await

首先需要注意的是在文章指明的 NodeJs 和 Chrome 版本中,f(await promise)完全等同于promise.then(f)。

當(dāng)然,討論promise的時(shí)候,我們也不能拋開(kāi)async await。雖然兩者在 promise 狀態(tài)為 onResolve 時(shí)處理邏輯相同,但錯(cuò)誤處理的執(zhí)行邏輯并不一樣,在async await中發(fā)生錯(cuò)誤時(shí),才是真正的直接跳過(guò)后續(xù)await的執(zhí)行

const promiseReject = new Promise((resolve, reject) => { reject(new Error(’錯(cuò)誤’))})const promiseResolve1 = new Promise((resolve, reject) => { resolve(’正確’)})const promiseResolve2 = new Promise((resolve, reject) => { resolve(’正確’)})const promiseResolve3 = new Promise((resolve, reject) => { resolve(’正確’)})function demo1 () { promiseReject .then(() => {console.log(’1-1’) }) .catch(err => {console.log(’1-2’) })}async function demo2 () { try {await promiseRejectawait promiseResolve1await promiseResolve2await promiseResolve3 } catch (error) {console.log(’2-1’) }}// 2-1// 1-2

以上就是JS異步代碼單元測(cè)試之神奇的Promise的詳細(xì)內(nèi)容,更多關(guān)于JS異步代碼之Promise的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 清纯唯美激情 | 中文字幕久久精品 | 开心激情网五月天 | 天天操天天操天天操天天操天天操 | 欧美区在线 | 国产激情影院 | 国产视频网站在线观看 | 91麻豆精品国产91久久综合 | 国产成人综合在线 | 国产三区av | 午夜视频免费在线观看 | 亚洲国产精品久久 | 日韩中文在线观看 | 97在线观看视频免费 | 深夜福利一区二区 | 人人干av| 国产日韩欧美视频在线观看 | 国产精品日韩欧美大师 | 狼干综合| 国产精品麻豆免费版 | 97青草| 日韩精品六区 | 国产成人三级在线观看视频 | 黄网页在线观看 | 国产中出| 国产另类精品 | 久久久888 | 久久国产美女视频 | 亚洲自拍网站 | 亚洲黄色一级大片 | 欧美精品久久久 | 成人v精品蜜桃久一区 | 国产中文一区 | 成人黄色在线免费观看 | 亚洲精品视频在线 | 亚洲第一毛片 | 天天综合天天色 | 亚洲午夜精品在线 | 欧美精品导航 | 日韩一区二区三区在线播放 | 成人av影院 |