關於async 中return 和 return await 的差別

  小七平時在使用ES2017的 async功能常常會有以下:promise

const bluebird = require('bluebird');

async function doSomething() {
    await bluebird.delay(1000);
    throw new Error('ttt');
}

(async function() {
    return doSomething();// 關注點
})()
    .then(function() {
        console.log('ok');
    })
    .catch(function(err) {
        console.error('fail');
    });

小七在調用doSomething的時候直接使用 `return doSomething()` ,而不是用 `return await doSomething()`。async

由於它們的執行和結果都是同樣的。在大部分狀況下,這種方式是正確的,並且代碼也比較簡潔。函數

但事實上在執行的時候是有些差別的,咱們看下下面的例子。ui

(async function() {
    try {
        return doSomething();// 關注點,這裏咱們省略了await 產生了更咱們設想不太同樣的結果
    } catch (err) {
        console.log('do something ignore');
    }
})()
    .then(function() {
        console.log('ok');
    })
    .catch(function(err) {
        console.error('fail');
    });
//輸出 :fail

小七這裏本來的設想是 在調用doSomething的時候,若是有什麼錯誤的話,忽略錯誤,正常返回。spa

可是結果確實拋出了錯誤,被最後面的catch捕獲。輸出了fail。code

因而調整了下代碼:blog

const bluebird = require('bluebird');

async function doSomething() {
    await bluebird.delay(1000);
    throw new Error('ttt');
}

(async function() {
    try {
        return await doSomething();// 關注點,這裏恢復了省略掉的 await
    } catch (err) {
        console.log('do something ignore');
    }
})()
    .then(function() {
        console.log('ok');
    })
    .catch(function(err) {
        console.error('fail');
    });
//輸出 :
//do something ignore
//ok

把 await 恢復回來就正常了。同步

這裏主要的緣由就在於小七對async語法糖原理的誤解,小七覺得在async函數中使用return的時候和return await是同樣的,是由於return 隱含了await的功能。然而並不是如此,async中的return 只是簡單的返回一個promise,因此return 在使用的時候並無任何拋錯,try catch 天然就無法得到該錯誤。而返回的promise被後面的.catch方法捕獲到錯誤。it

而若是使用  return await doSomething() 的時候,等價於 先await了doSomething返回的promise,若是有reject,則會直接傳給cacth block 處理。io

 

總結,async函數中的return 並無黑魔法,在大部分狀況下也不須要黑魔法,由於async方法的結果也是一個promise,因此返回一個promise是等價的。

但咱們仍是要理解它的實現原理。

由於在async 中 try catch 語法糖的原理是處理同步拋出的錯誤和await產生的reject,因此,咱們不能省略掉await的調用。

相關文章
相關標籤/搜索