一、基础
1、特点
- 分为三个阶段
- pending:初始状态,非 成功 / 失败 状态
- fulfilled(resolved):操作成功
- rejected:操作失败
- 阶段不会自动改变,需要手动调用
_new promise(function(_**_resolve, reject_**_){})_
中的 resolve()将状态更改为 fulfilled,以及 rejected() 将状态更改为 rejected - 一旦状态被改变,就无法再改变(状态终生只能改变一次)
```javascript
// 先把 promise 的状态改为失败,再尝试改为成功
// 最后结果仍未失败状态,因为状态只能变更一次,第二次改成功状态无效
let foo = () => {
return new Promise((resolve, reject) => {
}); }reject('操作失败!');
resolve('操作成功!');
let successFun = data => { console.log(‘成功回调!!,数据为:’ + data); }
let p = foo().then(successFun, null);
console.log(p);

- 若错过了状态变更的第一时间,之后再去监听变更,也能获取到结果(对比事件 event,事件若错过了第一时间,之后再去获取事件是获取不到的)
```javascript
// 下面代码,未第一时间监听到 promise 状态的改变
// 但输出结果仍能正常监听
let foo = () => {
return new Promise((resolve, reject) => {
resolve('123');
reject('操作失败!');
});
}
let successFun = data => {
console.log('成功回调!!,数据为:' + data);
}
let p = foo();
setTimeout(() => {
console.log('计时器函数执行!');
p.then(successFun, null);
}, 2000);
console.log('外部代码执行完毕!');
2、优点
- 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
- promise 对象提供了统一的接口,使得控制异步操作更加容易
3、缺点
- 无法取消 promise,一旦新建它就会立即执行
```javascript
let foo = () => {
return new Promise((resolve, reject) => {
}); }console.log('Promise 对象被新建了!');
foo(); console.log(‘同步的代码!’);
// 输出顺序如下,说明 promise 一旦创建就会立即执行 // Promise 对象被新建了! // 同步的代码!
- 若不设置回调函数,promise 内部抛出的异常无法被外部捕获
```javascript
// 首先看正常的代码
throw new Error('外部抛出异常!');
console.log('同步的代码!');
// 一旦出现了异常,之后的代码就不会执行
// 再看 promise,异常会正常抛出,但不会阻止外部代码正常执行
let foo = () => {
return new Promise((resolve, reject) => {
console.log('Promise 对象被新建了!');
throw new Error('内部抛出异常!');
});
}
let p = foo();
console.log('同步的代码!');
// 另外
- 当 promise 处于 pending 阶段时,无法得知目前进展到哪个阶段(刚开始还是即将完成)
二、用法
1、基础用法
- 通过
**_resolve(data)_**
**_reject(data)_**
变更 promise 的状态,同时 data 数据即为外部监听器得到的数据 ```javascript let foo = () => { return new Promise((resolve, reject) => {
}); }let data = { name: '军大侠', sex: '男' } resolve(data);
let successFun = data => { console.log(‘成功回调!!必须有成功回调函数’); console.log(data); } let failFun = data => { console.log(‘失败回调!!失败回调函数可为空’); }
let p = foo(); p.then(successFun, null);

<a name="cXd9D"></a>
#### 2、回调函数执行顺序
- 无论 promise 的状态是何时改变的,回调函数永远是最后执行
```javascript
let foo = () => {
return new Promise((resolve, reject) => {
console.log('内部开始执行!');
resolve();
console.log('内部执行完毕!');
});
}
let successFun = data => {
console.log('成功回调!!');
}
foo().then(successFun, null);
console.log('外部执行完毕!!');
- 回调函数的优先级高于计时器(前者属于js引擎,后者属于浏览器API)
```javascript
let foo = () => {
return new Promise((resolve, reject) => {
}); }console.log('内部开始执行!'); resolve(); console.log('内部执行完毕!');
let successFun = data => { console.log(‘成功回调!!’); }
setTimeout(() => { console.log(‘计时器即时输出!!’); }, 0); foo().then(successFun, null); console.log(‘外部执行完毕!!’);

<a name="jOxwI"></a>
#### 3、链式编程
- 原理:每个 promise 的 then 中,返回一个新的 promise
```javascript
let foo = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功的数据!');
}, 1000);
});
}
foo().then(data => { // 第一个 promise 的监听
return new Promise((res, rej) => {
res(data += "11")
})
}).then(data => { // 第二个 promise 的监听
return new Promise((res, rej) => {
res(data += "22");
})
}).then(data => { // 第三个 promise 的监听
console.log(data);
})
- 上述代码可以简写成如下
```javascript
let foo = () => {
return new Promise((resolve, reject) => {
}); }setTimeout(() => { resolve('成功的数据!'); }, 1000);
foo().then(data => { // 第一个 promise 的监听 return Promise.resolve(data += “11”); }).then(data => { // 第二个 promise 的监听 return Promise.resolve(data += “22”); }).then(data => { // 第三个 promise 的监听 console.log(data); })
- 甚至可以再简化
```javascript
let foo = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功的数据!');
}, 1000);
});
}
foo().then(data => { // 第一个 promise 的监听
return data += "11"
}).then(data => { // 第二个 promise 的监听
return data += "22"
}).then(data => { // 第三个 promise 的监听
console.log(data);
})
- 但 reject 的简化方法只有
**_return Promise.reject(data += "11")_**
- 当 then 未指定处理 rejected 状态的失败函数时,会抛出异常
```javascript
let foo = () => {
return new Promise((resolve, reject) => {
}); }setTimeout(() => { resolve('成功的数据!'); }, 1000);
foo().then(data => { // 第一个 promise 的监听 return data += “11” }).then(data => { // 第二个 promise 的监听 return Promise.reject(data += “22”); }).then(data => { // 第三个 promise 的监听 console.log(data); })

- 指定了失败处理函数时,则会执行失败处理函数
```javascript
let foo = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('成功的数据!');
}, 1000);
});
}
foo().then(data => { // 第一个 promise 的监听
return data
}).then(data => { // 第二个 promise 的监听
return Promise.reject();
}).then(data => { // 第三个 promise 的监听
console.log("成功!!");
}, () => {
console.log('失败!!');
})