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

2021-07-13 14:02:49 +08:00
 autoxbc

姐妹篇
如果你自认熟悉 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');
		}
	}
} )();
6039 次点击
所在节点    JavaScript
35 条回复
Jirajine
2021-07-13 19:07:41 +08:00
@learningman 不用等人,我自己就是 go 黑。这里我想说的是 union type 。
mx1700
2021-07-13 20:55:00 +08:00
这题出的挺好,不知道为什么楼上一些人不认同
Actrace
2021-07-13 21:20:49 +08:00
@mx1700 因为如果工作中写这种代码的同事可能会被打断腿。
muzuiget
2021-07-13 21:50:13 +08:00
for( const key in Obj ) 不保证顺序吧,所有情况都有可能。
dorr
2021-07-13 21:50:49 +08:00
@mx1700 可读性太差了,维护的同事会打人的
Biwood
2021-07-13 22:05:14 +08:00
把最后的 for…in 改成数组遍历更严谨一些,16 楼正解

另外,感觉 async 关键字现在很容易被滥用,就说你这个题里面,除去包含 await 操作的函数,其他几个函数根本就不需要用到 async
no1xsyzy
2021-07-14 09:44:14 +08:00
await 会把 Promise<Promise<X>> 直接返回到 X 还行……
finalwave
2021-07-14 10:24:03 +08:00
@no1xsyzy async 里返回 Promise 的时候就自动把 Promise<Promise<X>>解成 Promise<X>了,不是 await 这一步干的
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
2021-07-14 10:46:42 +08:00
蒙古上单 不请自来
libook
2021-07-14 11:20:33 +08:00
@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
2021-07-14 11:32:32 +08:00
如果生产代码写成这样。。。出 bug 了,写个这个要被拉出来打一顿。。看到都气人。
我写代码追究一个原则,简单明了偷懒。能少判断绝对少判断,能不重复写的代码绝不重复写。
Marszm
2021-07-14 11:36:57 +08:00
再说一个点。。。async...await,promise,他们出现的原因就是 JS 的硬伤回调地狱。。为了简化复杂逻辑流而搞出来的语法糖。。然后你们面试想办法把一个简化代码复杂度的玩意搞的贼复杂。有自虐倾向对吧。。
不过我也认同,还是要明白其中的原理。但是真的面试能不出这种题么。谁平时代码写成这样?
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
2021-07-14 12:37:46 +08:00
@Actrace
@dorr 人家出这题目本来就为了考察对知识点的掌握情况吧,出题本来不就应该是高度抽象考察对概念的理解吗,也没人说工作中会这样写啊。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/789253

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX