如果你觉得await将原本异步操作变成了同步阻塞的,那你应该对await产生了误解。
事实上,我在早期学习的时候也对 await 有这样的误解,比如说 await setTimeout(XXX, 3000)
会将代码阻塞3秒,相当于Java中的 Thread.sleep(3000)
,但这个理解是错误的。
generator
async/await 是 generator 的语法糖,不用手动调用 next
函数。
先考虑异步操作的特点,最主要的就是注册顺序确定,但执行顺序不确定,就算连续出现多个异步操作,也无法保证他们的回调是顺序运行的。为了控制回调的执行顺序,以往的方法是在回调中注册异步操作,显而易见,这个会造成“回调地狱”,但 generator 中的yield就能有效解决这个问题。
和return
不同,使用yield
能在generator中“返回”多次,比如说有3个 yield
,每次调用 next
函数,都会执行到 yield
后暂停,直到再次调用 next
函数,在 yield
执行一个异步操作就能以平铺的形式去设置顺序敏感的操作,在每次“返回”之后都能去做其他的事情。
await
generator需要调用next
函数去继续运行,await
会自动使用 next
,无需显式调用,在多个连续的 await
中,每次都会等待本次操作完成后再执行下一个操作,但这并不是同步阻塞的,这里是协程,在异步完成前程序该做什么就做什么,在完成后 await
会获取执行结果,接着运行后面的代码。
所以就算在Controller中使用了 await
,比如进行 BCrypt 运算,在运算的过程中,程序依然会正常运行下去,在运算结束拿到结果后才会继续运行下去。