Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第一题:以下代码输出什么,为什么? #1

Closed
KieSun opened this issue Mar 7, 2021 · 44 comments
Closed

第一题:以下代码输出什么,为什么? #1

KieSun opened this issue Mar 7, 2021 · 44 comments

Comments

@KieSun
Copy link
Owner

KieSun commented Mar 7, 2021

try {
    (async function() { a().b().c() })()
} catch (e) {
    console.log(`执行出错:${e.message}`)
}

第一反应答案是什么?为什么会这样报错?

答案

新建了一个大厂真题每日打卡群,有意愿学习打卡的再进,群已达扫码上线,请加好友拉你进群

@KieSun KieSun added the 字节 label Mar 8, 2021
@turkyden
Copy link

turkyden commented Mar 8, 2021

Fucking Awesome !

- VM404:2 Uncaught (in promise) ReferenceError: a is not defined
  • a 函数未定义,a is not defined
  • try catch 无法捕获异步错误
  • async 是 Generator 生成器的语法糖,会报发生在 in Promise 错误

@ganfubin
Copy link

ganfubin commented Mar 8, 2021

a is not defined

@RoJoHub
Copy link

RoJoHub commented Mar 8, 2021

ReferenceError: a is not defined
a 都没有定义

@GuoYueXin
Copy link

GuoYueXin commented Mar 8, 2021

ReferenceError: a is not defined
try catch 无法捕获异步错误

@EstherHuo
Copy link

a is not defined

1 similar comment
@xiaoCongxyx
Copy link

a is not defined

@barry7
Copy link

barry7 commented Mar 8, 2021

async 约等于 Promise

@chen870370470
Copy link

执行try中语句时报错ReferenceError: a is not defined,因此catch也捕获不到错误。

@pengpeng9413
Copy link

ReferenceError: a is not defined

@HydratedPig
Copy link

ReferenceError: a is not defined
(async function() {a().b().c() })()是个异步任务,try...catch无法捕捉,所以不会执行catch中的console
改成

try {
    await (async function() { a().b().c() })()
} catch (e) {
    console.log(`执行出错:${e.message}`)
}

就可以catch啦执行出错:a is not defined

@tuhongwei
Copy link

tuhongwei commented Mar 8, 2021

执行a()时,因为a未定义,所以会报错
但因为try里面async是异步,所以不会被同步的catch捕获,即不会有console输出
最终会返回一个rejected的Promise, 所以报的错为 Uncaught (in promise) ReferenceError: a is not defined

@wanCheng7
Copy link

a is not defined

@weiChow
Copy link

weiChow commented Mar 8, 2021

ReferenceError: a is not defined

async定义的是异步任务,catch无法捕获

@jshuaishuai
Copy link

如果有异步函数的话,就不需要用try catch 了

@free-qiaochen
Copy link

ReferenceError: a is not defined;
try执行,async方法出错,相当于promise reject,错误没被catch捕获

@tinyKingBear
Copy link

what‘s the fuck you doing here?

@pengpeng9413
Copy link

至于为啥catch 没有捕捉到,楼上很多的人都没有解释很清楚,我来回答一下我的陋见:
async + function 返回的是一个promise,promise 在自执行(FFEE)的一个作用域中是个完整的异步函数自执行了,内层函数已经执行完了,外层当然catch 不到。
想要被catch ,是在try 中发生了错误,代码中断。而一个完整promise只会在自身这一层被捕获,外面认为你这是自己的事,不能管啊。出来闹,我就管!

@zhihuifanqiechaodan
Copy link

try catch 不能捕获异步代码。 所以也不是单纯的考量promise吧。虽然他也属于异步

@XINXINP
Copy link

XINXINP commented Mar 8, 2021

1.try catch捕获不到该错误
2.按照正常语法来说 错误应该是 ReferenceError类型 a is not defined
3.可以修改一下 加一个await关键字 获取promise的返回值,使其能够被捕获到
4.也可以直接使用promise自带的catch捕获错误 (与题目无关了)

@ambit-tsai
Copy link

image

@PointMountain
Copy link
Contributor

1.try里面是一个自执行的async函数,async是异步的方法,try catch没办法捕获到异步方法
2.async函数返回的是promise,因为内部发生了错误,所以变成promise rejected了,错误则是a方法未定义

@blacklike
Copy link

个人见解: try catch是同步的,而async是异步的,返回的是一个Promise。而try catch只能捕获到同步函数中的异常,无法捕获到异步函数中的异常错误。而async中执行的,a().b().c(),一开始的a就会报错,因为a未定义。报错为:Uncaught ReferenceError: a is not defined
at :1:1

@pengpeng9413
Copy link

我又要来提灵魂之问了?为啥try catch 不能捕获异步任务的error ,这跟浏览器的执行机制(事件循环)有关:
try catch 作为宏任务而promise是微任务,当执行promise.then(()=>callbaclk()),进入回调函数的时候,外层try catch 这个宏任务已经出栈了,跟他已经没有关系了

@cduyzh
Copy link

cduyzh commented Mar 8, 2021

  1. ReferenceError: a is not defined
  2. 执行异步方法a().b().c()的时候 try catch已经出栈执行完毕

给出2个例子 方便理解

// 异步,宏任务
try {
	setTimeout(function() {
		console.log(b);
	}, 0);
} catch (error) {
	console.log('error', error); // 这里是不会执行的
}
console.log('out try catch')

// 异步,微任务
try {
	new Promise(() => {
		throw new Error('new promise throw error');
	});
} catch (error) {
	console.log('error', error);
}

原因是因为:当异步函数抛出异常时,对于宏任务而言,执行函数时已经将该函数推入栈,此时并不在 try-catch 所在的栈,所以 try-catch 并不能捕获到错误。对于微任务而言,比如 promise,promise 的构造函数的异常只能被自带的 reject 也就是.catch 函数捕获到。

@ctime-zliang
Copy link

ctime-zliang commented Mar 8, 2021

try {
    let a = 0
    ;(async function() {
        a += 1
        console.log('inner', a)
        throw new Error('123')
        // a()
    })()
    console.log('outer', a)
} catch(e) {
    console.warn('Error', e)
}

这段代码,inner 会在 outer 之前输出,为啥?

@caryye
Copy link

caryye commented Mar 8, 2021

ReferenceError: a is not defined
try catch正常来说是可以捕获到错误的,但是由于try里面的是异步任务;try catch作为宏任务,在函数执行的时候就已经入栈,而当异步函数抛出异常时,try catch已出栈

@zhihuifanqiechaodan
Copy link

zhihuifanqiechaodan commented Mar 8, 2021

try {
    let a = 0
    ;(async function() {
        a += 1
        console.log('inner', a)
        throw new Error('123')
        // a()
    })()
    console.log('outer', a)
} catch(e) {
    console.warn('Error', e)
}

这段代码,inner 会在 outer 之前输出,为啥?

promise是异步。 throw new Error('123')的时候错误被promise.reject接收,然后继续执行同步代码,等同步代码执行完执行异步爆出这个错误

@ctime-zliang
Copy link

try {
    let a = 0
    ;(async function() {
        a += 1
        console.log('inner', a)
        throw new Error('123')
        // a()
    })()
    console.log('outer', a)
} catch(e) {
    console.warn('Error', e)
}

这段代码,inner 会在 outer 之前输出,为啥?

本人补充一下,为啥要等 outer 输出完后,再抛错

@KieSun
Copy link
Owner Author

KieSun commented Mar 8, 2021

ReferenceError: a is not defined
(async function() {a().b().c() })()是个异步任务,try...catch无法捕捉,所以不会执行catch中的console
改成

try {
    await (async function() { a().b().c() })()
} catch (e) {
    console.log(`执行出错:${e.message}`)
}

就可以catch啦执行出错:a is not defined

老哥,你是第一位给出完整答案的,如果需要简历修改服务可以发我邮箱:zx597813039@gmail.com

@littleKnave
Copy link

ReferenceError: a is not defined

  1. 立即执行(async function() {a().b().c() })()。因为返回是一个promise,所以返回一个promise.reject
  2. 执行完接下来的同步任务,这时候执行完try...catch
  3. 执行promise.reject,报错

@KieSun
Copy link
Owner Author

KieSun commented Mar 8, 2021

答案已经公布,地址

@ambit-tsai
Copy link

感觉上述的答案并不对。
从 async/await 的语法糖实现来看,题中的 async 函数是放在new Promise(executorFunc)executorFunc函数中执行的,众所周知executorFunc是立即执行,所以不存在什么异步任务。
而错误为什么不被 try/catch 捕获,是因为 Promise 在实例化的时候会捕获executorFunc的错误,所以外面是捕获不到的。

@cn1001wang
Copy link

感觉上述的答案并不对。
从 async/await 的语法糖实现来看,题中的 async 函数是放在new Promise(executorFunc)executorFunc函数中执行的,众所周知executorFunc是立即执行,所以不存在什么异步任务。
而错误为什么不被 try/catch 捕获,是因为 Promise 在实例化的时候会捕获executorFunc的错误,所以外面是捕获不到的。

我感觉你说的才是正确的,我昨天也是第一次知道Promise中的错误不会被抛到外部了。然后搜索一圈,就找到这么一篇文章翻译自V8引擎作者的文章 从JS引擎理解Await b()与Promise.then(b)的堆栈处理 。虽然不是和本次题目强关联,但也是在Promise与堆栈方面带给我所不知道的一面

try {
    let a = 0
    ;(async function() {
        a += 1
        console.log('inner', a)
        throw new Error('123')
        // a()
    })()
    console.log('outer', a)
} catch(e) {
    console.warn('Error', e)
}

如上代码,他是能够输出'outer' 1 的 ; try catch认为你这段代码没有错,所以进不了catch。Promise内部的错误应该在Promise中解决。
我想请教你有没有相关文章能够佐证这个观点。

;(function(){
    let p
    try {
        let a = 0
        p=Promise.resolve(1).then(e=>a())
        console.log('outer', a)
    } catch(e) {
        console.warn('Error', e)
    }
    setTimeout(()=>{
        p.catch(e=>{console.warn(e)})
    },1000)
})()

然后我有这么一段代码,我惊奇的发现chrome控制台会在1s后把错误输出给吞回去;输出warnning。
这是什么原理

@KieSun
Copy link
Owner Author

KieSun commented Mar 9, 2021

感觉上述的答案并不对。
从 async/await 的语法糖实现来看,题中的 async 函数是放在new Promise(executorFunc)executorFunc函数中执行的,众所周知executorFunc是立即执行,所以不存在什么异步任务。
而错误为什么不被 try/catch 捕获,是因为 Promise 在实例化的时候会捕获executorFunc的错误,所以外面是捕获不到的。

我感觉你说的才是正确的,我昨天也是第一次知道Promise中的错误不会被抛到外部了。然后搜索一圈,就找到这么一篇文章翻译自V8引擎作者的文章 从JS引擎理解Await b()与Promise.then(b)的堆栈处理 。虽然不是和本次题目强关联,但也是在Promise与堆栈方面带给我所不知道的一面

try {
let a = 0
;(async function() {
a += 1
console.log('inner', a)
throw new Error('123')
// a()
})()
console.log('outer', a)
} catch(e) {
console.warn('Error', e)
}
如上代码,他是能够输出'outer' 1 的 ; try catch认为你这段代码没有错,所以进不了catch。Promise内部的错误应该在Promise中解决。
我想请教你有没有相关文章能够佐证这个观点。

;(function(){
let p
try {
let a = 0
p=Promise.resolve(1).then(e=>a())
console.log('outer', a)
} catch(e) {
console.warn('Error', e)
}
setTimeout(()=>{
p.catch(e=>{console.warn(e)})
},1000)
})()
然后我有这么一段代码,我惊奇的发现chrome控制台会在1s后把错误输出给吞回去;输出warnning。
这是什么原理

这种问题其实其实查标准就好了:

内部 throw 被 promise reject 了,外部就不可能捕获到这个错误,当然不管有没有这个机制都是捕获不到的,毕竟异步代码怎么让同步代码捕获错误。

标准具体地址

@ambit-tsai
Copy link

如上图,从 ECMA-262 的27.7.5.1 AsyncFunctionStart一节来看,async 函数是立即执行的,执行结果出现异常时reject

  1. Set the code evaluation state of asyncContext such that when evaluation is resumed for that execution context the following steps will be performed:
    a. Let result be the result of evaluating asyncFunctionBody.
    ...
    d. If result.[[Type]] is normal, then
        i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
    e. Else if result.[[Type]] is return, then
        i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »).
    f. Else,
        i. Assert: result.[[Type]] is throw.
        ii. Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
    g. Return.

至于第二个问题,众所周知当 Promise 异常未被捕获时,会报Uncaught (in promise) TypeError,翻了下 ECMA-262 好像没有明确规定,延迟捕获异常要怎么办。Chrome 会吞回去,Firefox 并不会,大概是自行发挥的结果吧。
@cn1001wang

@cn1001wang
Copy link

@ambit-tsai @KieSun 感谢二位, execution context stack 我还得再研究研究 !

@startfromscratch
Copy link

try{
(async function(){
await a().b().c()
})()
}catch(e){
console.log(e,'报错原因-------')
}

1 首先 try catch (同步)异常 报错 会执行 catch
2 async 是一个promise 语法糖 返回一个 promise
3 在 async 执行栈中 a b c 3个方法
4 在执行a的时候 会直接报错 a is nodefind
5 async 会返回 promise 其实在这里应该是有一个错误 但是 浏览器 读取到 a方法的错误, 到此为止 在不考虑任何因素的情况下 同步的捕获异常 肯定是捕获不到异步的方法里面的问题。

@wuqiren
Copy link

wuqiren commented Mar 15, 2021

a is not defined

@NanYun-rs
Copy link

try {
    (async function() { a().b().c() })()
} catch (e) {
    console.log(`执行出错:${e.message}`)
}
  1. 执行出现异常 Uncaught (in promise) ReferenceError: a is not defined
  2. try catch 无法捕获异常

@KieSun KieSun added the 异步 label Mar 20, 2021
@hua-bang
Copy link

游览器会抛出异常 a is not defined
因为try catch无法捕获异步方法中的错误

@DaisyX-BOT
Copy link

  1. 执行结果 Uncaught (in promise) ReferenceError: a is not defined
  2. try catch 无法捕获异常
  3. 需要看看大佬们的见解,我理解的不透测

@xiaocongWang
Copy link

个人觉得这道题考察的是 async 函数执行出错时语言层面是怎么处理的,而不是异步导致 try catch 无法捕获错误。(async function() { a().b().c() })() 并没有涉及到异步。

@ambit-tsai 的解释比较靠谱

@rookielzy
Copy link
Contributor

  1. 结果为 Uncaught (in promise) ReferenceError: a is not defined
  2. try catch 是同步代码,无法捕捉异步代码中的错误
  3. 在 async 中,执行了未定义的 a(),因此这时候的错误被 Promise.reject 捕捉

@zjhlaap
Copy link

zjhlaap commented May 20, 2021

a is not defined
函数前加上async相当于把它放到了promise的executor函数内,变成了异步
因为try catch没办法捕获到异步的错误,想要得到执行出错:a is not defined的结果需要把捕获写到函数内部
图片

@KieSun KieSun closed this as completed Sep 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests