Navigation Menu

Skip to content

Commit

Permalink
docs(advanced): edit promise
Browse files Browse the repository at this point in the history
  • Loading branch information
ruanyf committed Feb 4, 2017
1 parent 0577bb7 commit 27c8a88
Showing 1 changed file with 12 additions and 24 deletions.
36 changes: 12 additions & 24 deletions advanced/promise.md
Expand Up @@ -6,46 +6,36 @@ date: 2012-12-22
modifiedOn: 2013-11-28
---

Promise是JavaScript异步操作解决方案。介绍Promise之前,先对异步操作做一个详细介绍。
Promise 是 JavaScript 异步操作解决方案。介绍 Promise 之前,先对异步操作做一个详细介绍。

## JavaScript的异步执行

### 概述

Javascript语言的执行环境是"单线程"(single thread)。所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务。
Javascript 语言的执行环境是“单线程(single thread)。所谓单线程,就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务。

这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。
这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段 JavaScript 代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。

JavaScript语言本身并不慢,慢的是读写外部数据,比如等待Ajax请求返回结果。这个时候,如果对方服务器迟迟没有响应,或者网络不通畅,就会导致脚本的长时间停滞。
JavaScript 语言本身并不慢,慢的是读写外部数据,比如等待 Ajax 请求返回结果。这个时候,如果对方服务器迟迟没有响应,或者网络不通畅,就会导致脚本的长时间停滞。

为了解决这个问题,Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。"同步模式"就是传统做法,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的。这往往用于一些简单的、快速的、不涉及读写的操作
为了解决这个问题,Javascript 语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。同步模式就是传统做法,后一个任务等待前一个任务结束,然后再执行,程序的执行顺序与任务的排列顺序是一致的、同步的。这往往用于一些简单的、快速的、不涉及 IO 读写的操作

"异步模式"则完全不同,每一个任务分成两段,第一段代码包含对外部数据的请求,第二段代码被写成一个回调函数,包含了对外部数据的处理。第一段代码执行完,不是立刻执行第二段代码,而是将程序的执行权交给第二个任务。等到外部数据返回了,再由系统通知执行第二段代码。所以,程序的执行顺序与任务的排列顺序是不一致的、异步的。
异步模式则完全不同,每一个任务分成两段,第一段代码包含对外部数据的请求,第二段代码被写成一个回调函数,包含了对外部数据的处理。第一段代码执行完,不是立刻执行第二段代码,而是将程序的执行权交给第二个任务。等到外部数据返回了,再由系统通知执行第二段代码。所以,程序的执行顺序与任务的排列顺序是不一致的、异步的。

以下总结了"异步模式"编程的几种方法,理解它们可以让你写出结构更合理、性能更出色、维护更方便的JavaScript程序
以下总结了"异步模式"编程的几种方法,理解它们可以让你写出结构更合理、性能更出色、维护更方便的 JavaScript 程序

### 回调函数

回调函数是异步编程最基本的方法。

假定有两个函数f1和f2,后者等待前者的执行结果。

```javascript
f1();
f2();
```

上面代码中,`f2`必须要等到`f1`执行完,才能执行。

如果`f1`是一个很耗时的任务,可以考虑改写`f1`,把`f2`写成`f1`的回调函数。
假定有两个函数`f1``f2`,后者必须等到前者执行完成,才能执行。这时,可以考虑改写`f1`,把`f2`写成`f1`的回调函数。

```javascript
function f1(callback) {
setTimeout(function () {
// f1的任务代码
// ...
callback();
}, 0);
// f1 的代码

// f1 执行完成后,调用回调函数
callback();
}
```

Expand All @@ -55,8 +45,6 @@ function f1(callback) {
f1(f2);
```

采用这种方式,我们把同步操作变成了异步操作,`setTimeout(fn, 0)``fn`放到下一轮事件循环执行。`f1`不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。

回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度[耦合](http://en.wikipedia.org/wiki/Coupling_(computer_programming))(Coupling),使得程序结构混乱、流程难以追踪(尤其是回调函数嵌套的情况),而且每个任务只能指定一个回调函数。

### 事件监听
Expand Down

0 comments on commit 27c8a88

Please sign in to comment.