关于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的调用。

相关文章
相关标签/搜索