同步任务与异步任务
同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
异步任务:不进入主线程、而进入"任务队列"(task queue)的任务,只有等主线程任务执行完毕,"任务队列"开始通知主线程,请求执行任务,该任务才会进入主线程执行。
事件队列
- JavaScript是单线程的,所有的同步任务都会在主线程中执行
- 主线程之外,还有一个任务队列。每当一个异步任务有结果了,就往任务队列中塞一个时间。
- 当主线程中所有任务都完成了之后,系统会依次读取队列中的事件,与之相对应的异步任务进入主线程,开始执行。
- 异步任务之间,会存在差异,所以它们的执行优先级是不同的。大致分为微任务,如:Promise, MutationObserver,和宏任务, 如setTimeout, setInterval和I/O等。同一事件循环中,微任务永远在宏任务前执行。
注意: 当new一个Promise是,其resolve中的代码会立即执行 - 主线程会不断重复上面的步骤,直到执行完所有任务。
async/await概念
-
async函数,可以理解为Generator函数的语法糖
async关键字: -
被asnyc操作符修饰的函数必然返回一个Promise时,
-
当asnyc函数返回一个值时,Promise的resolve方法负责传递
-
当asnyc函数抛出异常时,Promise的reject方法会传递这个异常值
-
建立在promise之上,总是和await一起使用的
-
await会返回一个promise对象或一个表达式的值
-
其目的是为了让异步操作更优雅,能像同步那样书写
Promise的链式then()是怎样执行的?
- Promise多个then链式调用,不是连续创建多个微任务并推入微任务队列的,因为每一个
then()
的返回值必然是一个Promise,而后续的then()
是上一步then()
返回的Promise的回调 - 传入Promise构造器的执行器函数内部的同步代码执行到
resolve()
,将Promise的状态改变为<resolve>: undefined
, 然后then中传入的回调函数console.log('1')
作为一个微任务被推入微任务队列中 - 第二个
then()
中传入的回调函数console.log('2')
此时还没有被推入微任务队列,只有上一个then()
中console.log('1')
执行完毕后才继续执行