|
1 |
| -Promise 入门 |
2 |
| -======== |
| 1 | +Promise 详解 |
| 2 | +======== |
| 3 | + |
| 4 | +我们先来看 Promise 的用法。 |
| 5 | + |
| 6 | +```javascript |
| 7 | +new Promise( |
| 8 | + /* 执行器 executor */ |
| 9 | + function (resolve, reject) { |
| 10 | + // 一段耗时很长的异步操作 |
| 11 | + |
| 12 | + resolve(); // 数据处理完成 |
| 13 | + |
| 14 | + reject(); // 数据处理出错 |
| 15 | + } |
| 16 | +) |
| 17 | + .then(function A() { |
| 18 | + // 成功,下一步 |
| 19 | + }, function B() { |
| 20 | + // 失败,做相应处理 |
| 21 | + }); |
| 22 | +``` |
| 23 | + |
| 24 | +Promise 是一个**代理对象**,它和原先的异步操作并无关系。它接受一个“执行器 executor”作为参数,我们要把原先要执行的异步(并非一定要异步,以后会说明,这里你可以先不深究)操作放进去。 |
| 25 | + |
| 26 | +执行器在 Promise 实例创建后立刻开始执行。执行器自带两个参数:`resolve` 和 `reject`,这二位都是函数,执行它们会改变 Promise 实例的状态。 |
| 27 | + |
| 28 | +Promise 实例有三个状态: |
| 29 | + |
| 30 | +1. `pending` [待定] 初始状态,新创建的实例处于这个状态 |
| 31 | +2. `fulfilled` [实现] 操作成功,在执行器里调用 `resolve()` 之后,实例切换到这个状态 |
| 32 | +3. `rejected` [被否决] 操作失败,在执行器里调用 `reject()` 之后,实例切换到这个状态 |
| 33 | + |
| 34 | +Promise 实例状态改变之后,就会触发后面对应的 `.then()` 参数里的函数,继续执行后续步骤。另外,Promise 的实例状态只会改变一次,确定为 `fulfilled` 或 `rejected` 之一后就不会再变。 |
| 35 | + |
| 36 | +## 一个简单的例子 |
| 37 | + |
| 38 | +```javascript |
| 39 | +new Promise( resolve => { |
| 40 | + setTimeout( () => { |
| 41 | + resolve('hello'); |
| 42 | + }, 2000); |
| 43 | +}) |
| 44 | + .then( value => { |
| 45 | + console.log( value + ' world'); |
| 46 | + }); |
| 47 | + |
| 48 | +// 输出: |
| 49 | +// hello world |
| 50 | +``` |
| 51 | + |
| 52 | +这是最简单的一种情况。执行器里面是一个定时器,2秒种之后,它会执行 `resolve('hello')`,将 Promise 实例的状态置为 `fulfilled`。接下来 `.then()` 里面的函数就会被触发,它接受前面 Promise 返回的值 `'hello'`,将其与 `' world'` 连接起来,输出“hello world”。 |
| 53 | + |
| 54 | +## 再来一个稍复杂的例子 |
| 55 | + |
| 56 | +```javascript |
| 57 | +new Promise( resolve => { |
| 58 | + setTimeout( () => { |
| 59 | + resolve('hello'); |
| 60 | + }, 2000); |
| 61 | +}) |
| 62 | + .then( value => { |
| 63 | + return new Promise( resolve => { |
| 64 | + setTimeout( () => { |
| 65 | + resolve('world') |
| 66 | + }, 2000); |
| 67 | + }); |
| 68 | + }) |
| 69 | + .then( value => { |
| 70 | + console.log( value + ' world'); |
| 71 | + }); |
| 72 | + |
| 73 | +// 输出: |
| 74 | +// world world |
| 75 | +``` |
| 76 | + |
| 77 | +这个例子与上一个例子的不同之处在于,我在 `.then()` 的后面又跟了一个 `.then()`。并且在第一个 `.then()` 里又返回了一个 Promise 实例。于是,第二个 `.then()` 就又等了2秒才执行,并且接收到的参数是第一个 `.then()` 返回的 Promise 返回的 `'world'`(好拗口),而不是起始 Promise 返回的 `'hello'`。 |
| 78 | + |
| 79 | +这就必须说明 Promise 里 `.then()` 的定义。 |
| 80 | + |
| 81 | +## `.then()` |
| 82 | + |
| 83 | +`.then()` 其实接受两个函数作为参数,分别代表 `fulfilled` 状态时的处理函数和 `rejected` 状态时的处理函数。只不过通常情况下,我会建议大家使用 `.catch()` 捕获 `rejected` 状态。这个后面还会说到,所以暂时按下不表。 |
| 84 | + |
| 85 | +`.then()` 会返回一个新的 Promise 实例,所以它可以链式调用,如前面的例子所示。当前面的 Promise 状态改变时,`.then()` 会执行特定的状态响应函数,并将其结果,调用自己的 Promise 的 `resolve()` 返回。 |
| 86 | + |
| 87 | +### Promise.resolve() |
| 88 | + |
| 89 | +这里必须补充一下 Promise.resolve() 的相关知识。它是 Promise 的静态方法,可以返回一个状态为 `fulfilled` 的 Promise 实例。 |
| 90 | + |
| 91 | +它可以接受四种不同类型的参数,并且返回不同的值: |
| 92 | + |
| 93 | +1. 参数为空,返回一个 `fulfilled` 实例,响应函数的参数也为空 |
| 94 | +2. 参数不为空、也不是 Promise 实例,返回 `fulfilled` 实例,只不过响应函数能得到这个参数 |
| 95 | +3. 参数为 Promise 实例,直接原样返回 |
| 96 | +4. 参数为 thenable 对象,里可以执行它的 `.then()` |
| 97 | + |
| 98 | +用一段代码来示范吧,比较简单,就不一一解释了。 |
| 99 | + |
| 100 | +```javascript |
| 101 | +Promise.resolve() |
| 102 | + .then( () => { |
| 103 | + console.log('Step 1'); |
| 104 | + return Promise.resolve('Hello'); |
| 105 | + }) |
| 106 | + .then( value => { |
| 107 | + console.log(value, 'World'); |
| 108 | + return Promise.resolve(new Promise( resolve => { |
| 109 | + setTimeout(() => { |
| 110 | + resolve('Good'); |
| 111 | + }, 2000); |
| 112 | + })); |
| 113 | + }) |
| 114 | + .then( value => { |
| 115 | + console.log(value, ' evening'); |
| 116 | + return Promise.resolve({ |
| 117 | + then() { |
| 118 | + console.log(', everyone'); |
| 119 | + } |
| 120 | + }) |
| 121 | + }); |
| 122 | + |
| 123 | +// 输出: |
| 124 | +// Step 1 |
| 125 | +// Hello World |
| 126 | +// (2秒之后) Good evening |
| 127 | +// , everyone |
| 128 | +``` |
| 129 | + |
| 130 | +### 继续 `.then()` 的话题 |
| 131 | + |
| 132 | +结合上一小节关于 Promise.resolve() 的讲解,我们应该可以推断出 `.then()` 里的状态响应函数不同返回结果对进程的影响了吧。 |
0 commit comments