《JavaScript异步编程》精读笔记

写在前面

  • 书籍介绍:本书讲述基本的异步处理技巧,包括PubSub、事件模式、Promises等,经过这些技巧,能够更好的应对大型Web应用程序的复杂性,交互快速响应的代码。理解了JavaScript的异步模式可让读者写出结构更合理、性能更出色、维护更方便的JavaScript程序。

第一章 深刻理解JavaScript事件

1.1.事件的调度

  • JavaScript代码用于不会被中断,由于代码在运行期间只须要排队事件便可,而这些事件在代码运行结束以前不会被触发

1.2.异步函数的类型

  • 每一种JavaScript环境都有本身的异步函数集
  • 在浏览器端,Ajax方法有一个可设置为false的async选项
  • 在Node.js中同步的API方法在名称上会有明确的标示如fs.readFileSync
  • WebKit的console.log打印输出并无当即拍摄对象快照,只存储了一个指向对象的引用,等代码返回事件队列才去打印输出快照
  • Node的console.log是严格同步的
  • 当同一个JavaScript进程正运行着代码时,任何JavaScript计时函数都没法使其余代码运行
  • setInterval调度事件设置成0,chrome等浏览器触发频率大约为200次/秒,node大约是1000次/秒
  • 替换成while循环时在Chrome中触发频率达到400万次/秒,在node中会达到500万次/秒
  • 须要更细粒度的计时,在node中使用process.nextTick,在现代浏览器中使用requestAnimationFrame(主意兼容性)

1.3.异步函数的编写

  • 要想确认某个函数异步与否,惟一的方法就是审查其源代码
  • 有些函数某些时候是异步的,但其余时候却不是
  • 大量延时的话,会形成巨大的计算荷载
  • 异步递归有一点很惧怕,即在等待任务完成期间,可触发延时的次数是不受限的
  • 永远不要定义一个潜在同步而返值却有可能用于回调的函数

1.4.异步错误的处理

  • JavaScript也容许抛出异常,随后再用一个try/catch语句块捕获
  • 正因如此,Node.js中的回调几乎老是接受一个错误做为其首个参数,这样就容许回调本身来决定如何处理这个错误
  • 始终记住,只能在回调内部处理源于回调的异步错误
  • 在浏览器环境中,windows.onerror能够捕获异常,若是返回true,则能阻止浏览器默认的错误处理行为
  • 在node中,相似的process对象的uncaughtException事件捕获错误,正常状况下,node应用会因未捕获的异常而当即退出
  • 但自Node0.8.4起,uncaughtException事件就被废弃了
  • domain对象是事件化对象,它将throw转化为error事件

1.5.嵌套式回调的解嵌套

  • 最多见的反模式作法是,回调内部再嵌套回调
  • 嵌套式回调诱惑咱们经过添加更多代码来添加更多特性,而不是将这些特性实现为可管理、可重用的代码片断
  • 按照惯例,请避免两层以上的函数嵌套

第二章 分布式事件

  • 但愿使用分布式事件:事件的蝴蝶偶然扇动下翅膀,整个应用处处都引起反应
  • PubSub意为发布/订阅,模式来分发事件
  • PubSub模式的一些具体表现:Node的EventEmitter对象,Backbone的事件化模型,JQuery的自定义事件

2.1.PubSub模式

  • Node中几乎全部的I/O都是EventEmitter对象:文件流、HTTP服务器,甚至是应用进程自己
  • 事件处理器自己没法知道本身是从事件队列中仍是从应用代码中运行的
  • 对于无需即刻发生的事情维持一个队列,并使用一个计时函数定时运行此队列中的下一项任务
  • PubSub简化了事件的命名、分发、堆积

2.2.事件化模型

  • 只要对象带有PubSub接口,就能够称之为事件化对象
  • 每次一个对象上的事件引起了一系列事件并最终对这个对象自己触发了相同的事件,结果就事件循环了
  • 事件化模型为咱们带来了一种将应用状态变化转换为事件的直观方式

2.3.jQuery自定义事件

  • jQuery简化了强大分布式事件系统向任何Web应用程序的移植
  • jQuery提供了非冒泡式的triggerHandler方法
  • jQuery的自定义事件容许直接经过DOM来表达DOM相关的事件,没必要再把DOM变化的状态复制到应用程序的其余地方

小结

  • PubSub模式尤为不适合一次性事件
  • 用于解决一次性事件问题的工具叫作Promise

第三章 Promise对象和Deferred对象

3.1.Promise极简史

  • Promise对象也和EventEmitter对象同样,容许向同一个事件绑定任意多个处理器(堆积技术)
  • 使用Promise对象的最大优点在于,能够轻松从现有Promise对象派生出新的Promise
  • 在通常性用法中,Promise、Deferred和Future这三个词大致可算做同义词

3.2.生成Promise对象

  • 准确的说,Deffered是Promise的超集,它比Promise多一项关键特性,能够直接触发
  • 重申一点:每一个Deferred对象都含有一个Promise对象,而每个Promise对象都表明者一个Deferred对象
  • Ajax是演示Promise的绝佳用例:每次对远程服务器额调用都或成功或失败,而咱们但愿以不一样的方式来处理这两种状况

3.3.向回调函数传递数据

  • 执行或拒绝Deferred对象时,提供的任何参数都会转发至相应的回调
  • resolve/reject能够直接将其上下文传递至本身所触发的回调

3.4.进度通知

  • jQuery1.7中为Promise对象新添了一种能够调用无数次的回调progress
  • 总结下,Promise对象接受3种回调形式:done、fail、progress

3.5.Promise对象的合并

  • Promise对象的逻辑合并技术有一个最多见的用例:断定一组异步任务什么时候完成

3.6.管道链接将来

  • JavaScript中经常没法便捷的执行一系列异步任务,一个主要缘由是没法在第一个任务结束以前就向第二个任务附加处理器
  • jQuery1.6为Promise对象新增pipe(管道)方法
  • promise.promise() === promise

3.7.jQuery与Promises/A的对比

  • jQuery使用resolve做为fail的反义词,而Promise/A使用的是fulfill。在Promise/A规范中,Promise对象不论是已履行仍是已失败,都是已执行

3.8.用Promise对象代替回调函数

  • 理想状况下,开始执行异步任务的任何函数都应该返回Promise对象
  • Promise大大有助于让意大利面式的回调趋于平滑,并且也是由于Promise能够很是轻松的协调这种类型的异步任务

第四章 Async.js的工做流控制

4.1.异步工做流的次序问题

  • 普通的异步代码根本没法保证按照作出调用次序来触发调用的回调

4.3.Async.js的任务组织技术

  • Async.js的数据收集方法解决了一个异步函数如何运用于一个数据集的问题
  • 异步函数序列的运行:async.series和async.waterfall
  • 便利的是Async.js按照任务列表的次序向完工事件处理器传递结果,而不是按照生成这些结果的次序
  • Async.js的内核与灵魂:为最多见的异步情景提供简单又省时的工具函数

4.4.异步工做流的动态排队技术

  • async.queue的底层基本理念使人想起DMV动态管理视图

第五章 worker对象的多线程技术

5.0.写在前面

  • 事件可以代替一种特殊的多线程,即应用程序进程可拆分红多个部分同时运行的多线程技术(或者经过中断技术虚拟实现,或者经过多个CPU内核真正实现)
  • 尽管只运行在一个线程上确实不理想,但天真的将应用直接分发给多个内核更加糟糕
  • 与不一样线程进行交互的方式与在JavaScript中进行I/O操做一摸同样
  • 同一个进程内的多个线程之间能够分享状态,而彼此独立的进程之间则不能
  • 在JavaScript环境中,由worker对象运行的并发代码历来不会分享状态

5.1.网页版的worker对象

  • 首要目标,在不损害DOM响应能力的前提下处理复杂的计算
  • 几种潜在用法:解码视频、加密通讯、解析网页式编辑器
  • 基于相似的理由,worker对象看不到全局的window对象和主线程及其余worker线程的任何对象
  • 经过postMessage发送的对象会透明的作序列化和反序列化,想一想JSON.parse与JSON.stringify
  • worker对象能够随意使用XMLHttpRequest
  • 还有一个importScripts函数能够同步加载并运行指定的脚本

5.2.cluster带来的Node版worker

  • node0.6后推出一个支持多个进程绑定同一个端口的API:cluster(群集)
  • 一般为追求最佳性能而使用cluster按每颗CPU内核分化出一个进程
  • Node版worker对象由cluster.fork()把运行本身的同一个脚本再次加载成一个独立的进程
  • 浏览器能够将任意多余的线程降格为后台任务,而node服务器则要留出计算资源保障其请求处理的主要任务
  • 最著名的魔法:多个worker对象试图监听一个TCP端口时,node利用内部消息来容许分享该端口
  • 一样,cluster对象有一个主线程和多个worker线程,之间基于一些带有序列化对象或附连字符串的事件
  • 为了尽量减小线程之间的通讯开销,线程间分享的状态应该存储在像Redis这样的外部数据库中

第六章 异步的脚本加载

  • 须要对脚本分而治之,那些负责让页面更好看、更好用的脚本应该当即加载,而那些能够待会再加载的脚本稍后加载

6.1.局限性与补充说明

  • 请尽可能避免使用内联技术
  • 请勿使用document.write
  • 只要知道document.write至关于操控DOM时的GOTO语句就好了

6.2.script标签的再认识

  • 现代浏览器中的script标签分红了两种新类型:经典型和非阻塞型
  • 流行将脚本放在页面body标签的尾部。一方面用户能够更快的看到页面,另外一方面能够主动亲密接触DOM而无需等待事件来触发本身
  • defer让咱们想到静静等待文档加载的有序排队场景,那么async就会让咱们想到混乱的无政府状态
  • 一个脚本即用defer又用async,则在那些同时支持的浏览器中,async会覆盖defer

6.3.可编程的脚本加载

  • 两种合理的方法来抓取并运行服务器脚本:生成Ajax请求并用eval函数处理响应;向DOM插入script标签
  • require.js强大的工具包可以自动和AMD技术一块儿捋顺哪怕最复杂的脚本依赖图
  • 若是要求根据条件来加载脚本,请考虑像yepnope这样的脚本加载器。若是站点大量相互依赖的脚本,请考虑require.js

写在后面

  • pdf书籍、笔记思惟导图、随书代码打包下载地址:https://pan.baidu.com/s/1WMzAciLMfTasiWFQjz4ftA(提取码:wd01)
  • 纸质书京东购买地址:后面补上(推荐使用纸质书来学习)
  • 为了方便在手机上查看,后面我会把这些笔记陆续发布到公众号“派三派四”,能够扫码关注一下,欢迎关注。
    扫码关注公众号
相关文章
相关标签/搜索