内容概要

  • 同步模式与异步模式
  • 事件循环与消息队列
  • 异步编程的几种方式
  • Promise异步方案、宏任务/微任务队列
  • Generator异步方案、Async/Await语法糖

同步模式 Synchronous

  • 排队执行
  • 会阻塞代码执行

    异步模式 Asynchronous

  • 并列执行

  • 代码的执行顺序混乱

回调函数

  • 所有异步编程方案的根基
  • 回调函数可以理解为一件你想要做的事情

Promise

  • 一种更优的异步编程解决方案
  • 链式调用

基本用法

  1. const promise = new Promise((resolve, reject) => {
  2. // 这里用于兑现承诺
  3. // resolve(100) // 承诺达成
  4. reject(new Error('promise rejected')) // 承诺失败
  5. })
  6. promise.then((value) => {
  7. console.log('resolved', value)
  8. },(error) => {
  9. console.log('rejected', error)
  10. })
  11. console.log('end')
  12. // end
  13. // promise rejected
  14. // 说明promise的then 和 失败回调都被放进异步队列

链式调用

  • Promise对象的then方法回返回一个全新的Promise 对象
  • 后面的then方法就是在为上一个then返回的Promise注册回调
  • 前面then方法中回调函数的返回值会作为后面then方法回调的参数
  • 如果回调中返回的是Promise,那后面then方法的回调会等待它的结束 ```javascript ajax(‘/api/uses.json’) .then(() => { console.log(111111) }) .then(() => { console.log(22222) }) .then(() => { console.log(33333) }) .then(() => { console.log(44444) return ‘foo’ }) .then((value) => { console.log(55555) console.log(value) })

/ 11111 22222 33333 44444 55555 foo /

  1. **异常处理**
  2. - 在代码中捕获每一个可能出现的异常
  3. - catch方法捕获异常
  4. **Promise.all 并行执行**
  5. - ** **等待所有任务结束,才会结束
  6. ```javascript
  7. var promise = new Promise.all([
  8. ajax('/api/user.json'),
  9. ajax('/api/user2.json')
  10. ])
  11. promise.then((values) => {
  12. console.log(values) // 返回数组
  13. }).catch((error) => {
  14. console.log(error)
  15. })

Promise.race

  • 只会等待第一个结束的任务

执行时序
js引擎是单线程的

  • 同步任务:所有在主线程上排队执行的任务都叫同步任务,只有前一个任务执行完毕,才会执行下一个任务
  • 异步任务:不进入主线程而进入“任务队列”执行的任务,只有等主线程的同步任务都执行完,任务队列里的异步任务才会进入主线程执行。
    • 异步任务包括宏任务和微任务
      • 宏任务(macro-task): script、setInterval、setTimeout、
      • 微任务(micro-task): Promise、process.nextTick
        • Promise 不全是异步任务,Promise 里面的代码是同步的,执行resolve或reject回调的时候,会把then或catch 回调放异步任务中的微任务队列
  • JS 引擎的运行机制
    • 所有的同步任务都在主线程上执行,形成一个执行栈
    • 主线程之外还一个任务队列,当异步任务有了运行结果,就会在任务队列放置一个事件
    • 当执行栈里的所有同步任务执行完毕,系统就会去读取任务队列,将事件对应的异步任务放到执行栈中继续执行
    • 主线程不断的重复执行上面的第三步
  • 执行顺序
    1. 执行栈中从上往下一次执行,同步任务直接执行,异步任务会被放到任务队列中
    2. 当所有的同步任务执行完毕,开始执行所有的异步任务(也就是任务队列里的任务)
    3. 首先会执行任务队列里所有的微任务
    4. 然后执行一个宏任务
    5. 然后再执行完所有的微任务
    6. 执行宏任务、所有的微任务… 以此类推,知道所有的任务执行完毕
  • 以上c到f 这个循环便是事件循环 event loop
  • 事件循环是js 实现异步的一种方法,也是javaScript 的运行机制

宏任务和微任务都是实现异步的方式

Generator 生成器函数


  • 函数名前加星号 * ,调用时函数不会立即执行,而是生成一个函数生成器的对象
  • 通过对象.next() 获取执行结果
  • 通过对象.throw() 抛出异常
  • yield 可以暂停生成器的执行
function * main() {
  try {

    const users = yield ajax('/api/uses.json')
    console.log(1)

    const posts = yield ajax('/api/posts.json')
    console.log(2)

    const uses1 = yield ajax('/api/uses1.json')
    console.log(3)

  } catch(e) {
    console.log(e)
  }
}
function co(generator) {
  const g = generator()

  function handleResult (result) {
    if(result.done) {
      result.value.then(data => {
        handleResult(g.next(data))
      }, error => {
      g.throw(error)
      })
    }
  }

  handleResult(g.next())
}

co(main);

/*
1
2
3
*/

Async/ Await 语法糖

  • 语言层面的一步编程标准
  • 目前主流用法 ```javascript async function main() { try {

    const users = await ajax(‘/api/uses.json’) console.log(1)

    const posts = await ajax(‘/api/posts.json’) console.log(2)

    const uses1 = await ajax(‘/api/uses1.json’) console.log(3)

    } catch(e) { console.log(e) } }

main()

/ 1 2 3 / ```