11---
2- title : JavaScript异步编程的模式
2+ title : Promise对象
33layout : page
44category : advanced
55date : 2012-12-22
66modifiedOn : 2013-11-28
77---
88
9- ## 概述
9+ ## JavaScript的异步执行
10+
11+ ### 概述
1012
1113Javascript语言的执行环境是"单线程"(single thread)。所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。
1214
@@ -20,7 +22,7 @@ Javascript语言的执行环境是"单线程"(single thread)。所谓"单线
2022
2123以下总结了"异步模式"编程的4种方法,理解它们可以让你写出结构更合理、性能更出色、维护更方便的JavaScript程序。
2224
23- ## 回调函数
25+ ### 回调函数
2426
2527回调函数是异步编程最基本的方法。
2628
@@ -57,9 +59,9 @@ f1(f2);
5759
5860采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。
5961
60- 回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度[ 耦合] (http://en.wikipedia.org/wiki/Coupling_ (computer_programming)(Coupling),使得程序结构混乱、流程难以追踪(尤其是回调函数嵌套的情况),而且每个任务只能指定一个回调函数。
62+ 回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度[ 耦合] ( http://en.wikipedia.org/wiki/Coupling_(computer_programming) ) (Coupling),使得程序结构混乱、流程难以追踪(尤其是回调函数嵌套的情况),而且每个任务只能指定一个回调函数。
6163
62- ## 事件监听
64+ ### 事件监听
6365
6466另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
6567
@@ -88,7 +90,7 @@ f1.trigger('done')表示,执行完成后,立即触发done事件,从而开
8890
8991这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以"[ 去耦合] ( http://en.wikipedia.org/wiki/Decoupling ) "(Decoupling),有利于实现模块化。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
9092
91- ## 发布/订阅
93+ ### 发布/订阅
9294
9395"事件"完全可以理解成"信号",如果存在一个"信号中心",某个任务执行完成,就向信号中心"发布"(publish)一个信号,其他任务可以向信号中心"订阅"(subscribe)这个信号,从而知道什么时候自己可以开始执行。这就叫做"[ 发布/订阅模式] ( http://en.wikipedia.org/wiki/Publish-subscribe_pattern ) "(publish-subscribe pattern),又称"[ 观察者模式] ( http://en.wikipedia.org/wiki/Observer_pattern ) "(observer pattern)。
9496
@@ -127,7 +129,7 @@ jQuery.unsubscribe("done", f2);
127129
128130这种方法的性质与"事件监听"类似,但是明显优于后者。因为我们可以通过查看"消息中心",了解存在多少信号、每个信号有多少订阅者,从而监控程序的运行。
129131
130- ## Promises对象
132+ ## Promise对象
131133
132134### 简介
133135
@@ -174,12 +176,16 @@ step1(function (value1) {
174176
175177Promises原本只是社区提出的一个构想,一些外部函数库率先实现了这个功能,目前ECMAScript 6正在考虑将其写入语言标准,Chrome和Firefox浏览器的最新版本都初步部署了这个功能。
176178
177- ### Promises接口
179+ ### Promise接口
178180
179181当异步任务返回一个promise对象(小写表示这是Promise的实例)时,该对象只有三种状态:未完成(pending)、已完成(fulfilled)、失败(rejected)。
180182
181183这三种的状态的变化途径只有两个,且只能发生一次:从“未完成”到“已完成”,或者从“未完成”到“失败”。一旦当前状态变为“已完成”或“失败”,就意味着不会再发生状态变化了。
182184
185+ Promise对象的运行结果,最终只有两种。
186+
187+ - 得到一个值,状态变为fulfilled
188+ - 抛出一个错误,状态变为rejected
183189
184190promise对象的then方法用来添加回调函数。它可以接受两个回调函数,第一个是操作成功(fulfilled)时的回调函数,第二个是操作失败(rejected)时的回调函数(可以不提供)。一旦状态改变,就调用相应的回调函数。
185191
@@ -197,6 +203,24 @@ promise对象的then方法用来添加回调函数。它可以接受两个回调
197203
198204console.log和console.error这两个最后的回调函数,用法上有一点重要的区别。console.log只显示回调函数step4的返回值,而console.error可以显示step2、step3、step4之中任何一个发生的错误。也就是说,假定step2操作失败,抛出一个错误,这时step3和step4都不会再运行了,promises对象开始寻找接下来的第一个错误回调函数,在上面代码中是console.error。所以,结论就是Promises对象的错误有传递性。
199205
206+ 换言之,上面的代码等同于下面的形式。
207+
208+ ``` javascript
209+
210+ try {
211+ var v1 = step1 ();
212+ var v2 = step2 (v1);
213+ var v3 = step3 (v2);
214+ var v4 = step4 (v3);
215+ console .log (v4);
216+ } catch (error) {
217+ console .error (error);
218+ }
219+
220+ ```
221+
222+ 上面代码表示,try部分任何一步的错误,都会被catch部分捕获,并导致整个Promise操作的停止。
223+
200224### Promises对象的实现
201225
202226Promises只是一个规范,JavaScript语言原生还未提供支持。一般来说,总是选用现成的函数库。为了真正理解Promises对象,下面我们自己动手写一个Promises的实现。
0 commit comments