我认为await阻塞线程的说法不正确, 大家讨论一下

来源:2-8 深入理解async和await

GivenCui

2019-06-23

await会暂停当前 async function 的执行,等待 Promise 处理完成, async内是阻塞的, async外是非阻塞的

const mockAsyn = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('等待2秒')
    }, 2000)
  })
}

const testAsyn = async () => {
  console.log('1')

  const res = await mockAsyn()
  console.log('2', res)
}

testAsyn()

console.log('3')
console.log('4')


// 1
// 3
// 4
// 2 等待2秒

若按照老师的说法, 阻塞了线程, 则结果应为:

// 1
// 2 等待2秒
// 3
// 4

js是单线程的, 如果阻塞了线程, 那么就相当于卡住了, 所以这个说法是不对的
p.s. async function是基于generator的, 根promise没啥关系, 只是一种更好的异步解决方案罢了…

写回答

4回答

7七月

2019-06-24

单线程要想实现并发,必须是要分隔到比线程更细粒度的机制上来执行代码,js里就是”任务“。课程这里没有更深入的讲解宏任务和微任务,毕竟不是js语法课,能理解到await的等待就够了。有兴趣的同学可以看看后面的章节的深入讲解,并自行了解下宏任务和微任务。不过感谢指出这个说法,我后面补充下课程,强调下,阻塞线程只是一个便于理解的说法。同学很不错,有自己的思考,继续加油。

2
1
GivenCui
非常感谢!
2019-06-25
共1条回复

7七月

2019-06-24

这个后面有深入的讲解,js有宏任务和微任务的区别。单线程是不可能让线程不工作的,只是会把任务挂起。另外这个基于generator这个就不做解释了,说的不是一个层面的东西,他当然是基于generator的语法糖,但和promise连用才有意义。


3
2
7七月
回复
GivenCui
这些不会有官方的说法。不过我认为谷歌上搜到的很多资料特别是国外的博客是比较准确的。
2019-06-27
共2条回复

灿烂__

2020-03-05

同学 这个其实是eventLoop的相关知识点,只要是异步,都会放到异步进程里,当主线程同步任务执行完毕,任务队列就调取异步的分线程来执行。然后异步event事件队列是先进先出,每个异步都会执行 ,但是异步也分宏任务微任务,setTimeout是宏任务,Promise是微任务,而在async和await中,async是同步进行,函数体内await前面的代码是走同步的,await后面的代码是异步微任务,因为await后面就是promise.then()里的代码,所以js在执行完这次宏任务完成后,会执行相关微任务,再次执行下一次的宏任务,和他所带的微任务,知道异步进程里的任务都被执行完。

理清事件循环之后,回头来看你的问题,首先定义了两个方法,但并未执行,然后执行testAsyn(),1先输出,接着调用了mockAsyn函数,这放到了异步队列里,先不执行,然后再看下一行的console数字2,也是await后面的,也不执行,接着执行同步代码,输出3和4,然后回来看这次执行种牵带着的微任务 mockAsync调用,而在mockAsync种是返回一个宏任务setTimeout,然后放到下一次异步队列中,第一次事件循环完成,然后第二次事件循环,等待两秒,执行之前放入的队列中的宏任务,打印“等待2秒”,因为之前await是有关系到这一次setTimeout的,所以2属于上一次事件循环中的,所以要比setTimeout“等待2秒”先打印。故而顺序是1 3 4      2  等待2秒。

那么为什么2没有先和第一次事件循环一起打印,而要等待2秒呢,那就是因为老师说的await阻塞的线程这个原因。

同学若觉得我没讲清或着有错误的地方,也可以自行查阅有关事件循环eventLoop的相关知识,再来这里告知,大家一起加油~

1
0

苏湘门第

2020-02-09

感谢同学提问,我默默的将你的promise代码敲了一遍,继续看课程,希望会有解答

0
0

Node.js+Koa2+MySQL打造前后端分离精品项目《旧岛》

理解异步编程本质/培养面向对象思维,独立完成Node.js服务端开发

2223 学习 · 878 问题

查看课程