Promise是什么
Promise 是一种异步编程的解决方案,比传统的异步解决方案【回调函数】和【事件】更合理、更强大。
诞生的原因
异步网络请求的回调地狱,而且我们还得对每次请求的结果进行一些处理,代码会更加臃肿。一张图完美诠释:
不够?再加一张:
Promise的三种状态
- pedding 等待(默认状态。异步代码执行完毕后会转换为以下两种状态)
- resolve 成功
- reject 失败
基本用法
语法
- Promise:
- 构造函数
- 接受一个参数:callback,我们把要执行的异步任务放置在这个callback中
- then:
- Promise对象下的一个方法:该方法在Promise对象的状态发生改变的时候触发then的回调
1 2 3 4 5 6 7 8 9 10 11 12 13
| function asyncFun(){ return new Promise((resolve, reject) => { if (resolve) { resolve(); }else{ reject(new Error()); } }) }
asyncFun().then().then()...
|
Promise特性
立即执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| let p = new Promise((resolve, reject) => { console.log("一个Promise对象被创建出来"); resolve("success"); });
console.log("flag");
p.then((data) => { console.log(data); });
|
状态不可逆
1 2 3 4 5 6 7 8 9 10 11
| let p = new Promise((resolve, reject) => { resolve("success"); reject("reject"); });
p.then((data) => { console.log(data); });
|
链式调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let p = new Promise((resolve, reject) => { setTimeout(() => { console.log(1); reject(); }, 1000); });
p.then(() => { console.log('成功'); }, () => { console.log('失败'); } );
|
then的回调异步性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let p = new Promise((resolve, reject) => { console.log("我是Promise的callback中的代码"); setTimeout(() => { resolve("我1s后才会被执行"); }, 1000); });
p.then((data) => { console.log(data); });
console.log("我是主线程中的同步代码");
|
解释:Promise 的 callback 回调函数中的代码是立即执行的(setTimeout 这个定时器也是立即执行的,只是函数内的 resolve 被延迟1s执行,跟 Promise 本身的立即执行没关系),但 then 方法中的回调函数执行则是异步的,因此,"我1s后才会被执行"
会在最后输出。
异常的捕获
Promise的异常有两种方法可以捕获,一种是 then 的第二个回调;一种 .catch()
来捕获前一个 Promise 抛出的错误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| let p = new Promise((resolve, reject) => { reject("error"); });
p.then(data => { console.log("success") }, error => { console.log(error); });
let p = new Promise((resolve, reject) => { reject("error"); });
p.then(data => { console.log("success") }).catch(error => { console.log("catch:" + error); });
|
Promise.all 和 Promise.race
Promise.all
Promise.all 接收一个参数,它必须是可以迭代的,例如数组。
它通常用来处理一些并发的异步操作,即它们的结果互不干扰,但是又需要异步执行。当所有 Promise 都成功的时候,整个 Promise.all 才成功。成功调用后返回一个数组,数组的值是有序的,顺序就是传入参数的数组顺序:
成功的情况
1 2 3 4 5 6 7 8 9 10 11 12
| let arr = [1, 2, 3]; let tasks = arr.map(num => { return new Promise((resolve, reject) => { resolve(num * 5); }); });
Promise.all(tasks).then(data => { console.log(arr); console.log(data); });
|
失败的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| let arr = [1, 2, 3]; let tasks = arr.map(num => { return new Promise((resolve, reject) => { if (num === 3) { reject('rejected'); } resolve(num * 5); }); });
Promise.all(tasks).then(data => { console.log(arr); console.log(data); }).catch(err => { console.log(err); });
|
Promise.race
Promise.race 和 Promise.all 类似,都接收一个可以迭代的参数,但是不同之处是 Promise.race 的状态变化不是全部受参数内的状态影响,一旦参数内有一个值的状态发生的改变,那么该 Promise 的状态就是改变的状态。就跟 race 单词的字面意思一样,谁跑的快谁赢。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let p1 = new Promise((resolve, reject) => { setTimeout(resolve, 300, 'p1 doned'); });
var p2 = new Promise((resolve, reject) => { setTimeout(resolve, 50, 'p2 doned'); });
var p3 = new Promise((resolve, reject) => { setTimeout(reject, 100, 'p3 rejected'); });
Promise.race([p1, p2, p3]).then(data => { console.log(data); }).catch(function(err) { console.log(err); });
|