简介
Promise是异步编程的一种解决方案,从语法上看,它属于构造函数,通过new的方式可以生产一个Promise对象,promise构造函数自身有all,reject,resolve等方法,原型链上有then,catch,finally等方法。Promise用于发送一个异步请求,在特定时间后返回结果。从它执行到返回结果有三种状态:pending(等待),fulfiled(成功),reject(失败),一旦状态改变,就不会再通过其他方式改变这种状态。
为什么有Promise
当回调函数嵌套层级很多的时候,代码的可读性很差,造成回调地狱,Promise就是用来解决:
- 回调地狱带来的代码可读性差
- promise支持多个并发请求,获取并发请求中的数据
promise可以解决异步问题,不能说promise本身是异步的
用法
(1)new
let p = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(() => {
console.log('执行完成');
resolve('ok');
}, 2000);
});
Promise的构造函数接收一个参数:函数(实际是对象),并且这个函数需要传入两个参数:
- resolve :异步操作执行成功后的回调函数
- reject:异步操作执行失败后的回调函数
(2)then链式操作
相比回调地狱的写法,promise的写法清晰很多:
p.then((data) => {
console.log(data);
})
.then((data) => {
console.log(data);
})
.then((data) => {
console.log(data);
(3) reject的用法
let p = new Promise((resolve, reject) => {
//做一些异步操作
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的随机数
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000);
});
p.then((data) => {
console.log('resolved',data);
},(err) => {
console.log('rejected',err);
}
);
then中传了两个参数,then方法可以接受两个参数,第一个对应resolve的回调,第二个对应reject的回调。
(4)catch的用法
catch和then的第二个参数一样,用来指定reject的回调:
p.then((data) => {
console.log('resolved',data);
}).catch((err) => {
console.log('rejected',err);
});
效果和写在then的第二个参数里面一样。不过它还有另外一个作用:在执行resolve的回调(也就是上面then中的第一个参数)时,如果抛出异常了(代码出错了),那么并不会报错卡死js,而是会进到这个catch方法中。
p.then((data) => {
console.log('resolved',data);
console.log(somedata); //此处的somedata未定义
})
.catch((err) => {
console.log('rejected',err);
});
(5)all
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
let Promise1 = new Promise(function(resolve, reject){})
let Promise2 = new Promise(function(resolve, reject){})
let Promise3 = new Promise(function(resolve, reject){})
let p = Promise.all([Promise1, Promise2, Promise3])
p.then(funciton(){
// 三个都成功则成功
}, function(){
// 只要有失败,则失败
})
(6)race
一旦某个promise解决或拒绝,返回的 promise就是执行快的那个promise的执行结果。需要注意的是,所有的promise都会被执行。
var a = 1;
var promise1 = new Promise(function(resolve, reject) {
setTimeout(function () {
resolve();
a = 2;
}, 2000, 'one');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(function () {
resolve();
a = 3;
}, 1000, 'two');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log("++"+a);
// Both resolve, but promise2 is faster
});
setTimeout(function () {
console.log("--"+a);
}, 3000, 'one');
结果:
++3
–2
分析:
最后一个setTimeout执行的时候,a的值是3,它是在前两个setTimeout执行之后才执行的,虽然Promise.race中接受到的是第二个定时器也就是1s后执行的,把a的值变为3,但是2s后第一个定时器也会执行,把a变为2。