-
Notifications
You must be signed in to change notification settings - Fork 836
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
第二题:以下代码输出什么,为什么? #2
Comments
inner 1 |
Fucking Awesome ! inner 1
outer 1
- VM489:6 Uncaught (in promise) Error: 123
|
输出结果:
原因:async定义了一个会返回promise的异步函数,此时作为宏任务执行,内部也是同步执行,直到抛出了异常被reject了,可以看做异步函数的回调,进入了微任务的队列中。 inner的a输出1很好理解,outer的a输出1是因为,在打印的时候 已经执行过a+=1了,异步方法内部形成了闭包,导致a能访问到外部变量a 新问题回答:async定义的方法默认一定会返回一个promise,这个promise要么会通过一个由async函数返回的值被resolve,要么会通过一个从async函数中抛出的(或其中没有被捕获到的)异常被reject。如果一个async函数的返回值看起来不是promise,那么它将会被隐式地包装在一个promise中。 有一个例子方便理解事件循环:微任务和宏任务
|
inner 1
|
let a = 0
;(async function() {
window.setTimeout(() => {
a += 1
console.log('inner', a)
}, 1000)
})()
console.log('outer', a) 这样的话 outer a 应该是 |
async作为一个语法糖,内部不碰到await 都是同步执行,promise的错误传播是不会冒泡的,所以外层捕获不到内层,作为语法糖只需要添加await就可以传播异常。inner 1 outher 1 throw。第一次整理答题,说的可能不对,见谅。 |
inner 1 宏任务进入宏任务队列,微任务进入微任务队列。 |
async并不是Promise的语法糖,它是Generator 函数的语法糖 |
输出结果:
个人理解:
|
结果
为什么首先执行自执行函数中的console, 然后会执行到thorw方法, 但是这个方式是一个被async function, 所以他的抛错会被延迟到微任务的结束,也就是后面的console会优先执行,执行完成之后才会去执行thorw抛出的错误,并且因为是一个微任务的原因,所以try...catch无法捕获 |
inner 1 |
执行结果如下: |
执行结果inner 1 理由可以把题目中的代码转化成下面代码
由于try{}catch(){}只能捕获同步代码的异常,因此无法捕获异步代码Promise中抛出的错误,所以最后会抛出Uncaught Error 新问题:async 是返回一个 Promise 对象,为啥函数体内的抛错能被返回的 Promise 捕获到转换过后的代码刚好解答了这个问题 |
inner 1 |
inner 1 async 返回的是一个Promise对象,其内部跑抛出的错误,无法被try...catch捕获. 而async定义的function的内部代码是同步的,所以会顺序执行先打印 inner 1,然后执行console语句打印 outer 1.接着遇到throw语句抛出错误. |
|
老哥,你是第一个完整答案的,需要简历修改的话直接微信群里和我说就行 |
输出结果:
回答:
|
try { 把题目补了一些细节 正常看到 这么简单呐 大概是 先执行 inner 1 接着 Erroe js不往下执行了,catch 报错 123 但是 它不讲理 在来看下补充的 添加了一个定时器 以及 throw 后继续打印了一个 log 实际上执行的结果是 inner 1 outer 1 以及 报错 123 最后是 1 定时器 看看为什么会这样 外层先不解释 直接看 async 里面的 async 是promise 语法糖 返回的是一个promise 在async 里面 抛出异常影响的是 promise promise 是异步 所有的异步里面 任意 抛出类似异常都不会影响 外层的执行 但是内部的执行一定会终止 ,可以改造一下 在async 前面 异步变同步 await 只要成同步 后续都会终止。 每一个宏任务都有自己的微任务 影响的只有自己 内部 而不会影响到外部。 |
try {
let a = 0
;(async function() {
a += 1
console.log('inner', a)
throw new Error('123')
})()
console.log('outer', a)
} catch(e) {
console.warn('Error', e)
} 和下面的代码是等价的: try {
let a = 0
;(function() {
return new Promise((resolve, reject) => {
a += 1
console.log('inner', a)
reject(new Error('123'))
})
})()
console.log('outer', a)
} catch(e) {
console.warn('Error', e)
} 又可以简化为: try {
let a = 0
new Promise((resolve, reject) => {
a += 1
console.log('inner', a)
reject(new Error('123'))
})
console.log('outer', a)
} catch(e) {
console.warn('Error', e)
} 答案inner 1
outer 1
Uncaught (in promise) Error: 123 涉及到的知识点
|
基础有点差,我居然认为立即执行函数形成一个独立的作用域,然后就没办法访问外部变量,自认为输出一个 a is not defined。 |
这道题目,前端基础不好的人,看别人的回答容易被人误导,分辨不出谁对谁错。 最好的方式是看规范。 还有就是 尝试手写 Promise ,手写 async await 的实现。 其次也可以看 babel 编译后的代码。 这道题目的关键是:Promise 内部的报错去哪了? |
答案: inner 1
outer 1
(node:18196) UnhandledPromiseRejectionWarning: Error: 123 跑去复习一波js的执行机制,直接自信。 try {
let a = 0;
function func() {
return new Promise((resolve, reject) => {
a += 1;
console.log('inner', a);
throw new Error('123')
});
}
func(); // (1)
console.log('outer', a);
} catch (e) {
console.log('出错了:', e);
}
// 我把上述代码(1)处改成
func().catch(err => {
console.log(err) // 123
}) 懂了,throw被隐式reject出去了。所以这个抛出错误的代码被当作微任务,整段js执行(第一次宏任务)后才开始执行微任务。 |
inner 1 |
从上一个问题中学习到
|
这道题目是昨天题目的演化版,更有趣了,当然本质是一样的,我们就当巩固了。
问题是输出顺序是什么,为什么会这样?
再加个问题,
async
是返回一个Promise
对象,为啥函数体内的抛错能被返回的Promise
捕获到。新建了一个大厂真题每日打卡群,有意愿学习打卡的再进,群已达扫码上线,请加好友拉你进群。
答案
The text was updated successfully, but these errors were encountered: