最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS異步代碼單元測試之神奇的Promise

 更新時間:2021年05月07日 14:11:44   作者:淺笑·  
這篇文章主要介紹了JS異步代碼單元測試之神奇的Promise,對異步感興趣的同學(xué),可以參考下

前言

寫這篇文章的起因是在寫單元測試時,做形如下測試時

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

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

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

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

為了不浪費大家的時間,我們先看一個例子:

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)
})

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

promise1-1 then

promise2-1 then

promise1-2 then

promise1-3 then

Error: mock error 1

promise1-4 then

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

MDN 的錯誤

我們?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ā)生異常時會停止,在鏈上查找 catch 語句來執(zhí)行。

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

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

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

這時我們需要知道then的一個默認(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 缺少了對應(yīng)狀態(tài)處理的回調(diào),那么 then 會自動生成一個接受此 promise 狀態(tài)的 promise,即 then 會返回一個狀態(tài)引用相同的 promsie,交給后續(xù)的調(diào)用。

那么上述代碼中的第二個 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')
// 注意這個 onRejected
}, (err) => {
    return Promise.reject(err)
})
.catch(err => {
    console.log(err)
})

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

簡寫

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

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('其實我是 promise2-3 then')
})

async await

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

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

const promiseReject = new Promise((resolve, reject) => {
    reject(new Error('錯誤'))
})
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 promiseReject
        await promiseResolve1
        await promiseResolve2
        await promiseResolve3
    } catch (error) {
        console.log('2-1')
    }
}
// 2-1
// 1-2

以上就是JS異步代碼單元測試之神奇的Promise的詳細(xì)內(nèi)容,更多關(guān)于JS異步代碼之Promise的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • javascript和jQuery實現(xiàn)網(wǎng)頁實時聊天的ajax長輪詢

    javascript和jQuery實現(xiàn)網(wǎng)頁實時聊天的ajax長輪詢

    在做網(wǎng)頁實時聊天的時候常常需要長輪詢,本文由于采用原生的JS及AJAX,所以簡單易懂,通過這篇文章就可以建立一個簡單的聊天室程序。
    2016-07-07
  • js基礎(chǔ)之DOM中元素對象的屬性方法詳解

    js基礎(chǔ)之DOM中元素對象的屬性方法詳解

    下面小編就為大家?guī)硪黄猨s基礎(chǔ)之DOM中元素對象的屬性方法詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • 深入學(xué)習(xí) JavaScript中的函數(shù)調(diào)用

    深入學(xué)習(xí) JavaScript中的函數(shù)調(diào)用

    可能很多人在學(xué)習(xí) JavaScript 過程中碰到過函數(shù)參數(shù)傳遞方式的迷惑,本著深入的精神,我給大家分享了一篇教程關(guān)于javascript中的函數(shù)調(diào)用知識,感興趣的朋友一起學(xué)習(xí)吧
    2017-03-03
  • 客戶端限制只能上傳jpg格式圖片的js代碼

    客戶端限制只能上傳jpg格式圖片的js代碼

    客戶端限制只能上傳jpg格式圖片的js代碼,對用戶體驗較好,適合網(wǎng)頁中只能使用jpg格式圖片的情況。
    2010-12-12
  • js頁面加載后執(zhí)行的幾種方式小結(jié)

    js頁面加載后執(zhí)行的幾種方式小結(jié)

    在實際應(yīng)用中往往需要在頁面加載完畢之后再去執(zhí)行相關(guān)的js代碼,之所以這么操作是有道理的,如果是操作dom元素,如果相關(guān)元素沒有加載完成,而去執(zhí)行js代碼,可能會導(dǎo)致錯誤
    2020-01-01
  • 淺析JavaScript中嚴(yán)格模式的使用

    淺析JavaScript中嚴(yán)格模式的使用

    在ECMAScript5標(biāo)準(zhǔn)中,JavaScript提出了嚴(yán)格模式的概念(Strict Mode),本文就來和大家簡單講講JavaScript中嚴(yán)格模式的具體使用,感興趣的可以了解一下
    2023-05-05
  • JS中用三種方式實現(xiàn)導(dǎo)航菜單中的二級下拉菜單

    JS中用三種方式實現(xiàn)導(dǎo)航菜單中的二級下拉菜單

    我們在淘寶、搜狐等大型網(wǎng)站上都可以看到使用的一些二級下拉菜單,比如下面這張圖片。那么如何實現(xiàn)導(dǎo)航菜單欄中的二級下拉菜單呢?下面小編給大家分享JS中用三種方式實現(xiàn)導(dǎo)航菜單中的二級下拉菜單,感興趣的朋友一起看看吧
    2016-10-10
  • javascript如何創(chuàng)建對象

    javascript如何創(chuàng)建對象

    這篇文章主要為大家詳細(xì)介紹了javascript創(chuàng)建對象的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-08-08
  • Aptos?SDK交互實現(xiàn)過程詳解

    Aptos?SDK交互實現(xiàn)過程詳解

    這篇文章主要為大家介紹了Aptos?SDK交互實現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • JS字符串的切分用法實例

    JS字符串的切分用法實例

    這篇文章主要介紹了JS字符串的切分的方法,結(jié)合實例形式分析了JavaScript使用split針對字符串進(jìn)行切分與遍歷的相關(guān)技巧,需要的朋友可以參考下
    2016-02-02

最新評論

类乌齐县| 晋城| 海口市| 宁陵县| 盐山县| 赫章县| 扎囊县| 正阳县| 肃宁县| 锡林浩特市| 彭州市| 凤山县| 普兰县| 西丰县| 米易县| 沐川县| 金乡县| 洛宁县| 宁阳县| 清流县| 东兴市| 安泽县| 关岭| 江都市| 偃师市| 宝坻区| 柯坪县| 读书| 永仁县| 大丰市| 两当县| 宝鸡市| 岑溪市| 元氏县| 蒲城县| 平昌县| 荆门市| 盐山县| 凤翔县| 泽州县| 汤阴县|