• 关于async 中return 和 return await 的差异


      小七平时在使用ES2017的 async功能经常会有如下:

    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 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的时候,如果有什么错误的话,忽略错误,正常返回。

    但是结果确实抛出了错误,被最后面的catch捕获。输出了fail。

    于是调整了下代码:

    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方法捕获到错误。

    而如果使用  return await doSomething() 的时候,等价于 先await了doSomething返回的promise,如果有reject,则会直接传给cacth block 处理。

    总结,async函数中的return 并没有黑魔法,在大部分情况下也不需要黑魔法,因为async方法的结果也是一个promise,所以返回一个promise是等价的。

    但我们还是要理解它的实现原理。

    因为在async 中 try catch 语法糖的原理是处理同步抛出的错误和await产生的reject,所以,我们不能省略掉await的调用。

  • 相关阅读:
    UCloud可用区的设计理念及功能图文详解
    Centos优化Hadoop
    Linux下使用fdisk扩展分区容量
    Linux内核之数据双链表
    安装 openSUSE Leap 42.1 之后要做的 8 件事
    Linux的防火墙–Iptables
    【转】c# thread.join 理解
    【转】Oracle 查询库中所有表名、字段名、表名说明、字段名说明
    【转】WinForms 使用Graphics绘制字体阴影
    WPF 如何加载图片
  • 原文地址:https://www.cnblogs.com/chianquan/p/9419089.html
Copyright © 2020-2023  润新知