如果你自认熟悉 async...await,来猜一下这个代码的运行结果 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
autoxbc
V2EX    Javascript

如果你自认熟悉 async...await,来猜一下这个代码的运行结果

  •  
  •   autoxbc 2021-07-13 14:02:49 +08:00 6537 次点击
    这是一个创建于 1552 天前的主题,其中的信息可能已经有所发展或是发生改变。

    姐妹篇
    如果你自认熟悉 Promise,来猜一下这个代码的运行结果

    要用猜的,别偷偷用浏览器运行

    const Err = async () => { throw new Error(42); }; const Obj = { async A (){ try { return Err(); } catch { console.log('A'); } }, async B (){ try { await Err(); } catch { console.log('B'); } }, async C (){ try { Err(); } catch { console.log('C'); } }, }; ( async () => { for( const key in Obj ) { try { await Obj[key](); } catch { console.log('D'); } } } )(); 
    第 1 条附言    2021-07-13 20:32:38 +08:00
    1. 这是标准的异步函数错误捕获,可不是茴字写法什么的
    2. 回复中已经有朋友认真解答知识点,这题的目的达到了
    35 条回复    2021-07-14 12:37:46 +08:00
    meeop
        1
    meeop  
       2021-07-13 14:06:54 +08:00   23
    既然还要猜,说明代码不清晰,可读性差,重写吧
    binux
        2
    binux  
       2021-07-13 14:09:36 +08:00 via Android
    DBD
    Zeffon
        3
    Zeffon  
       2021-07-13 14:12:58 +08:00
    DB 吧
    mxT52CRuqR6o5
        4
    mxT52CRuqR6o5  
       2021-07-13 14:15:23 +08:00
    想了一遍是 DB,运行一遍确实是 DB,不难啊
    binux
        5
    binux  
       2021-07-13 14:16:53 +08:00 via Android
    @mxT52CRuqR6o5 哦,B 没 rethrow,大意了
    mxT52CRuqR6o5
        6
    mxT52CRuqR6o5  
       2021-07-13 14:18:43 +08:00
    这个异常处理弄明白就行了,那个姐妹篇弄不明白也没关系
    ayase252
        7
    ayase252  
       2021-07-13 14:20:58 +08:00   3
    D
    B
    unhandled promise rejection
    Jirajine
        8
    Jirajine  
       2021-07-13 14:25:43 +08:00 via Android
    这就是为什么使用异常进行错误处理很糟糕,会把控制流搞得混乱。
    如果所有错误都用 Promise<value|error>的形式返回,一眼就能看出来。
    ericgui
        9
    ericgui  
       2021-07-13 14:26:35 +08:00
    这算是茴字的几种写法嘛
    xiangyuecn
        10
    xiangyuecn  
       2021-07-13 15:08:03 +08:00   2
    感觉:for in object 是一个玄学,应该不是有序的,大部分时候测试不出问题

    就像 HashMap 一样,大部分测试的时候是按 put 的顺序,就是不给你看到问题的机会
    ochatokori
        11
    ochatokori  
       2021-07-13 15:40:02 +08:00 via Android
    什么嘛,原来我对 promise 还挺熟悉的
    learningman
        12
    learningman  
       2021-07-13 15:45:07 +08:00
    @Jirajine #8 等下就有人骂你 if err!=nil
    mcfog
        13
    mcfog  
       2021-07-13 16:54:06 +08:00 via Android   2
    做这种人肉 v8 题做不出来也无所谓
    如果给结果要求解释讲不清楚就不行了
    但基本上很多人是能够讲个大概的,没什么区分度

    所以我不太喜欢面试被问到这类,也不会自己在面试中问这类问题
    RockShake
        14
    RockShake  
       2021-07-13 16:58:11 +08:00
    怎么感觉输出是在骂人
    Huelse
        15
    Huelse  
       2021-07-13 17:07:35 +08:00
    作为前端新手经验:await 才“执行”
    libook
        16
    libook  
       2021-07-13 17:08:55 +08:00   10
    这个掌握两个原理就行:
    1. async 函数返回 Promise ;
    2. Promise 只有被取值才能捕捉到错误,所以要么 Promise.prototype.catch(),要么就用 await+try/catch 。

    A 部分 Err()返回的是个 Promise,所以 try 不做不到错误,return 出去之后在主函数里 await,就取到了这个错误,被主函数的 try 捕捉到,输出 D 。

    B 部分 Err()返回 Promise,被 await 取到错误,被 B 的 try 捕捉到,输出 B 。

    C 部分 Err()返回 Promise,C 的 try 捕捉不到错误,因为 C()返回的是一个 undefined,所以主函数的 try 也捕捉不到这个错误,于是这一次循环什么都没输出。
    但是可能 JS 引擎会提示有一个 Uncaught 的异常,这个得看 JS 引擎的策略,有的引擎不提示,提示的话如果还输出 message 的话就会输出 42 。
    GiantHard
        17
    GiantHard  
       2021-07-13 18:22:19 +08:00 via Android   8
    如果你自认熟悉 js 类型转换,来猜一下这个代码的运行结果

    ```
    [!+[]+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]+[!+[]+!+[]+!+[]]
    ```

    要用猜的,别偷偷用浏览器运行
    SansXie
        18
    SansXie  
       2021-07-13 18:36:35 +08:00
    上次去面试遇到这种猜输出结果的, 心里暗暗在骂, 我自己面试别人重来不出这种题
    togou
        19
    togou  
       2021-07-13 18:38:11 +08:00
    写的太恶心了 直接 for await of [a(),b(),c()] 嘛
    mxT52CRuqR6o5
        20
    mxT52CRuqR6o5  
       2021-07-13 18:48:21 +08:00 via Android
    @xiangyuecn 新版 es 标准规定了 for in 遍历的顺序,是固定的,旧版 chrome 里 for in 的顺序和你具体的代码有关
    Jirajine
        21
    Jirajine  
       2021-07-13 19:07:41 +08:00 via Android
    @learningman 不用等人,我自己就是 go 黑。这里我想说的是 union type 。
    mx1700
        22
    mx1700  
       2021-07-13 20:55:00 +08:00 via Android   1
    这题出的挺好,不知道为什么楼上一些人不认同
    Actrace
        23
    Actrace  
       2021-07-13 21:20:49 +08:00   2
    @mx1700 因为如果工作中写这种代码的同事可能会被打断腿。
    muzuiget
        24
    muzuiget  
       2021-07-13 21:50:13 +08:00
    for( const key in Obj ) 不保证顺序吧,所有情况都有可能。
    dorr
        25
    dorr  
       2021-07-13 21:50:49 +08:00
    @mx1700 可读性太差了,维护的同事会打人的
    Biwood
        26
    Biwood  
       2021-07-13 22:05:14 +08:00 via iPhone
    把最后的 for…in 改成数组遍历更严谨一些,16 楼正解

    另外,感觉 async 关键字现在很容易被滥用,就说你这个题里面,除去包含 await 操作的函数,其他几个函数根本就不需要用到 async
    no1xsyzy
        27
    no1xsyzy  
       2021-07-14 09:44:14 +08:00
    await 会把 Promise<Promise<X>> 直接返回到 X 还行……
    finalwave
        28
    finalwave  
       2021-07-14 10:24:03 +08:00
    @no1xsyzy async 里返回 Promise 的时候就自动把 Promise<Promise<X>>解成 Promise<X>了,不是 await 这一步干的
    no1xsyzy
        29
    no1xsyzy  
       2021-07-14 10:34:48 +08:00
    @finalwave async 还这么做?我试了一下 await new Promise(r=>r(new Promise(r=>r(1))) 也这样应该是在 Promise 里面完成的?
    也就是说实际上不可能构造出 Promise<Promise<X>>?
    Email
        30
    Email  
       2021-07-14 10:46:42 +08:00
    蒙古上单 不请自来
    libook
        31
    libook  
       2021-07-14 11:20:33 +08:00   1
    @xiangyuecn #8
    @mxT52CRuqR6o5 #18
    @muzuiget #22

    关于顺序可以参考 ECMA-262 2022 的这个规范: https://tc39.es/ecma262/#sec-ordinaryownpropertykeys
    我看 ES6 的时候就是这样了,只不过章节名有变: https://262.ecma-international.org/6.0/#sec-ordinary-object-internal-methods-and-internal-slots-ownpropertykeys
    ES5.1 内容变化太大,没工夫看,有人看过可以发一下情况。

    翻译过来大义就是:
    1. 对象的属性如果可以被当做“array index”(如是数字或只包含数字的字符串)的话,就按照索引数值升序排序;
    2. 其他情况按照属性的创建时间升序排序。

    JS 的解析是按照代码自上而下的,所以题主给的这个代码的顺序是固定的,不会在执行中变化。
    Marszm
        32
    Marszm  
       2021-07-14 11:32:32 +08:00
    如果生产代码写成这样。。。出 bug 了,写个这个要被拉出来打一顿。。看到都气人。
    我写代码追究一个原则,简单明了偷懒。能少判断绝对少判断,能不重复写的代码绝不重复写。
    Marszm
        33
    Marszm  
       2021-07-14 11:36:57 +08:00
    说一个点。。。async...await,promise,他们出现的原因就是 JS 的硬伤回调地狱。。为了简化复杂逻辑流而搞出来的语法糖。。然后你们面试想办法把一个简化代码复杂度的玩意搞的贼复杂。有自虐倾向对吧。。
    不过我也认同,还是要明白其中的原理。但是真的面试能不出这种题么。谁平时代码写成这样?
    yzqtdu
        34
    yzqtdu  
       2021-07-14 12:05:52 +08:00
    这个问题对我还是蛮有意义的。除了上面大家总结的几点,我觉得这里还体现了 JS 里 Promise 对错误的处理,即 Promise 会“吞噬”传入函数的异常错误( http://jamesknelson.com/are-es6-promises-swallowing-your-errors/),并不会像普通函数一样,直接终止执行并解栈。当事件循环执行队列任务时,如果该 promise 对象之前执行过 catch 或 then 调用,新创建的 promise 才会异步执行传入函数,所以在 catch 里 throw 也是没法被外部捕获的,因为之前的执行栈已经解开了( https://stackoverflow.com/questions/30715367/why-can-i-not-throw-inside-a-promise-catch-handler
    daguaochengtang
        35
    daguaochengtang  
       2021-07-14 12:37:46 +08:00   1
    @Actrace
    @dorr 人家出这题目本来就为了考察对知识点的掌握情况吧,出题本来不就应该是高度抽象考察对概念的理解吗,也没人说工作中会这样写啊。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2756 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 14:30 PVG 22:30 LAX 07:30 JFK 10:30
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86