事件循环;控制台异步;Promise;生成器;async await;

书摘&心得

1、异步:现在与将来

  • 控制台是异步的,是宿主环境提供的。
    • console.log的改变是控制台I/O的异步化造成的
    • 解决方案1:使用debugger
    • 解决方案2:把对象序列化到一个字符串中JSON.stringify()
  • 事件循环
    • javaScript寄宿在宿主(浏览器)上
    • 宿主浏览器提供一种机制——事件循环,来执行多个块。
      • 事件循环的每一轮称为一个tick
      • 用户交互、I/O、定时器会向事件队列中插入事件
      • 同步操作会阻塞用户交互,锁定浏览器UI
    • javaScript引擎按需执行代码片段,宿主决定什么时候执行
      • setTimeout精度不高:定时器只是在指定时间后把回调挂入事件循环队列而已。【中卷143】
    • ES6本质上改变了由哪里管理事件循环
  • 并发
    • 看起来是同时工作,实际上是事件在交替执行
    • 门闩协调,保证只有第一名生效
    • 不霸占事件循环队列?搜索树大数据性能优化终极方案【155】
      • 可使用setTimeout(…0)进行异步调度——把这个函数插入到当前事件循环的结尾处。
      • 把自身分隔为更小的块
  • 任务队列 job queue【156】

    • 排在事件循环的每个tick之后

      2、回调

  • 回调函数包裹了程序的延续【162】

  • 回调相当于把函数交给第三方实现
  • 回调的缺陷
    • 与大脑的思维方式不相符
    • 控制反转,存在信任问题
  • 需要比回调更好的机制

    3、Promise

  • 反转再反转

    • 不由第三方执行回调,而是第三方提供时机,我自己根据时机决定代码的下一步
  • Promise构造函数
    • (fn),fn的参数是resolve函数和reject函数
    • 创建出来的就是promise对象image.png
    • 传入一个executor回调函数
      • executor可获得Promise内部的resolve和reject
      • 可在回调函数中执行resolve()或reject()
  • promise.then()
    • (onfulfilled,onreject),onfulfilled的参数是value,onreject的参数是reasonimage.png
    • 有两个参数,onfulfilled在promise对象resolved时执行,onrejected在promise对象rejected时执行。
    • promise.then本身会创建一个新的promise对象
  • promise承诺,未来发生,一旦许下不可变。
    • 未来值:关注promise的决议函数的返回值
    • 完成事件:关注promise的决议函数本身
  • 任何具有then方法的对象和函数即promise
  • 使用Promise.resolve()把函数封装一层调用then,能更好地建立信任

    4、生成器generator

  • 生成器是*fn,迭代器对象是g=fn()

    • 生成器是生产者,而迭代器是快递员:送入原料给生成器、输出产品给我们
  • 控制生成器需要调用迭代器对象g,g.next()可以才可以启动生成器
  • 消息传递是双向的
    • 迭代器对象g.next()可以获取yield时生成器的返回值
    • 迭代器对象g.next()也可以接收参数,向生成器注入参数代替暂停处的yield
    • 提问(next)与回答(yield/return)
  • 让异步的代码看起来像同步一样【中卷 250 读三遍】
    • 请求数据的时候遇到yeild暂停
    • 通过迭代器将请求到的数据传回生成器
    • 异步被抽象出去了,代码变得符合人脑逻辑,一团乱麻的回调bye bye
  • 完美世界:generator+promise(有点像dva的模式?)
    • yield出来一个promise对象
    • 在promise对象中恢复生成器
    • async await相当于把完美世界写进规范(好比js和jquery的关系?)
  • 生成器委托
    • 在一个生成器中使用另一个生成器yield *fn()
  • 形实转换程序【中卷 274】
    • javaScript中的thunk是指一个用于调用另外一个函数的函数,没有任何参数