async 實現原理分析

2022-06-22 21:42:12 字數 3458 閱讀 5864

遍歷器物件(generator 函式的返回值是乙個遍歷器物件)

generator 函式基礎語法(函式定義、yield 表示式、yield * 表示式)

generator.prototype.return 和 generator.prototype.throw

async 函式與 generator 函式不同在於下面幾點:

async 內建執行器,不用像 generator 函式那樣去反覆呼叫返回遍歷器的 next 方法

語義更好:async 表示非同步,await 表示等待非同步結果

await 後既可以是 promise 物件,也可以是原始型別的值

async 函式的返回值不是遍歷器物件,而是乙個 promise 物件,

正常使用:

let a = async () => 

a().then(res=>console.log(res))

// a() 返回乙個 promise 例項,

// a 函式裡 return 的值會作為成功**引數

錯誤處理:

let a = async () => 

a().catch(err=>console.log(err));

async 函式的實現原理就是將 generator 函式和自動執行器包裝在乙個函式裡。

async function fn(args)=> 

// 等同於

function fn(args) )

}

spawn 函式的實現如下:

function spawn(genf)  catch(err) 

/* async 執行完最後一步,return 的值會作為成功**引數 */

if (next.done)

/* asyc 還沒有執行完,await 後值存放在 next.value

將 next.value 轉化為 promise 例項,然後指定**為 step

就可以實現 generator 函式的自動執行 */

promise.resolve(next.value).then(

v => , // v 作為 await 返回值

e => // reject 時 await 沒有返回值

)} // 開始執行 async 函式

step( ()=>gen.next() );

})}

async 函式 return 原理:

async 函式本質還是 generator 函式,是通過不斷執行遍歷器物件的 next 方法來執行函式。當遍歷器物件遍歷完畢,就將最後遍歷 (return) 的值 resolve 出來傳遞給成功**

async 函式自動執行原理:

await 有兩個作用:

和 yield 一樣,可以將函式的執行進行切割和分步

可以將 await 後面的值轉化為 promise 例項,然後指定它的**。所以通過將 async 函式的下一步執行指定為這個 promise 例項的**,就可以實現 async 的自動執行。

await 返回值原理

我們知道, generator 函式遍歷器的 next 方法的引數,會作為上乙個 yield 的返回值。而 await 會指定其後 promise 的成功**執行遍歷器物件的 next 方法,我們再把 promise 的成功返回值作為 next 方法的引數,這個值就會成為 await 的返回值

async 出錯處理機制

分兩類:

async 函式裡的語句執行出錯。因為 async 函式的每一步,都是通過 try catch 執行的,所以錯誤都會**獲到然後 reject 傳遞給錯誤**

await 後的 promsie 例項被 reject 了。這樣會觸發 await 給該 promise 指定的錯誤**,這個錯誤**會呼叫 generator.prototype.throw 扔乙個錯誤到 async 函式裡面,如果裡面有 try catch 接住就讓它接住,然後繼續執行函式 (此時 await 語句出錯,不會有返回值);如果裡面沒有 try,這個 throw 的錯誤會被第一點所說的 try 接住,然後 reject 傳遞到錯誤**。

/* 1. 錯誤被外部接住 */ 

(async () => )()

.catch(err => console.log(err));

/* 2. 錯誤被內部接住 */

(async () => catch(e)

})()

.catch(err => console.log(err));

let b = async ()=> 

b().then(null, err=>console.log(err));

上面這個例子,會直接報錯,不會捕捉到錯誤然後執行錯誤**。

這是為什麼呢?

首先我們要知道promise 觸發錯誤**的前提:執行 reject 函式

而執行 reject 函式,有兩個前提:

開發者呼叫了 reject 函式

try catch 執行函式的時候捕獲到錯誤,將錯誤 reject 出來。

其中,第乙個是開發者可見,第二個是原始碼底層實現,開發者不可見

比如這個例子

new promise(()=>).catch(err=>console.log(err))

// 非同步函式其實會被 try catch 執行,一旦捕獲到錯誤,就 reject 掉

try catch (err)

// 而對於下面這個例子,錯誤是根本捕捉不到的

try catch (err)

所以我們知道,promise 真正捕獲到錯誤觸發錯誤**,關鍵還是在於 reject 函式是否有執行,而不是函式內部是否真的發生了錯誤。

回到開始,對於這個例子:

let b = async ()=> 

b().then(null, err=>console.log(err));

而在剛剛介紹 async 函式實現原理的時候,我們知道 async 函式在執行每一步的時候,也是用 try catch 去執行的:

try  catch (err)
剛剛我們已經說明過了,這樣子是捕捉不到錯誤的。

async函式的實現原理 例項

generator是實現async函式的關鍵 function helloworldgenerator var hw helloworldgenerator hw.next hw.next hw.next hw.next 複製 let fs require fs function readfile ...

async原理解析

async函式 async函式原理 常見的關於async的筆試題 async函式 const fs require fs const readfile function filename resolve data const foo function 複製 把上面 的generator函式 foo ...

SpringBoot實現 Async非同步

需要在啟動類加上 enableasync註解 呼叫service的話,把 async註解放到service實現類上。增加 async註解。在這裡要特殊注意返回futrue。如果需要返回結果只能用future。controller呼叫 isdone表示執行成功。這裡的while沒用。如果不是呼叫ser...