1、Promise概念
promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件使用起来更合理,简单来说,promise就是一个容器,里面存着某个(一个异步操作)的结果。
promise的特点
- 对象的状态不受外界的影响
- 一旦状态发生改变,就不会再改变,任何时候都可以得到这个结果
promise的状态
- pending表示异步操作进行中
- resolved表示异步成功
- rejected表示异步操作执行失败
只有异步操作的结果,可以决定当前是哪一种状态,任何操作都无法改变这个状态。
promise带来的问题 - 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
- 如果不设置回调函数,Promise内部抛出的错误,不会传到外部
- 当处于pending状态时,无法得知目前进展到哪一阶段(刚刚开始还是即将完成)
2、Promise的用法
2.1、Promise基本语法
let promise = new Promise(function(resolve,reject){
// resolve成功后的回调
// reject 失败后的回调
})
promise.then( res => {
console.log(res)
}, err => {
console.log(err)
})
2.2、示例
创建一个随机数,判断这个数是否小于5
let num = Math.floor(Math.random()*10)+1;
// 异步判断num
// 1.先新建一个Promise对象
let promise = new Promise(function(resolve,reject){
if(num < 5){
resolve('当前随机数小于5');
}else{
reject('当前随机数不小于5')
}
promise.then( res => {
console.log(res);
},err => {
console.log(err);
})
2.3、promise中的then方法
promise的then返回值还是一个promise对象,可以成员运算符调用then方法
promise.then( res => {
console.log(res);
}).catch( err => {
console.log(err);
})
then方法的参数为成功后执行,catch中的方法为失败后执行的内容。
Promise对象实例生成以后,可以使用then方法分别指定resolved状态和rejected状态的回调函数,也就是说,状态由实例化时的参数执行决定的,根据不同的状态,看成功还是失败即可判断出来。
resolve()和reject()的参数会传递到对应的回调函数的data或err,then返回的是一个新的Promise实例,也就是说还可以用返回的Promise实例对象继续调用then方法。
2.4、promise中的catch方法
catch()方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数,promise可以使用catch去捕获错误。
let num = Math.floor(Math.random()*10)+1;
// 异步判断num
// 1.先新建一个Promise对象
let promise = new Promise(function(resolve,reject){
if(num < 5){
resolve('当前随机数小于5');
}else{
reject('当前随机数不小于5')
}
});
promise.then( res => {
console.log('实例对象成功执行返回的数据')
}).catch( err => {
console.log(err);
})
}
2.5、链式写法
Promise的精髓是“状态”,用维护状态,传递状态的方式来使得回调函数能够及时调用,它比传递callback函数要简单、灵活很多。
//先创建promise异步对象实例
let promise = new Promise(function(resolve,reject){
$.ajax({
url:'https://jsonplaceholder.typicode.com/todos/1',
success:function(res){
resolve(res);
},
error:function(err){
reject(err)
}
})
}).then( res => {
$.ajax({
url:'https://jsonplaceholder.typicode.com/todos/2',
success:function(res){
resolve(res);
},
error:function(err){
reject(err)
}
})
}).then( res => {
$.ajax({
url:'https://jsonplaceholder.typicode.com/todos/3',
success:function(res){
resolve(res);
},
error:function(err){
reject(err)
}
})
})
2.6、resolve与reject方法
Promise的resolve()是在需要将现有对象转为Promise对象,Promise.resolve()方法就起到这个的作用
const obj = Promise.resolve(123);
console.log(typeof(obj));
console.log(obj);
2.7、Promise.resolve()的参数分成四种情况
- 参数是一个Promise实例对象
如果参数是promise实例,那么将会返回自身实例。 - 参数是一个thenable对象(具有then方法的对象)
// thenable示例
let thenable = {
then(resolve,reject){
resolve('thenable中resolve状态下的数据.');
}
}
let promise = Promise.resolve(thenable); //会将thenable转换为promise对象
// 并且立即执行thenable中的then方法
promise.then((res)=>{
console.log(res);
})
- 参数不是具有then方法,或不是对象
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve()返回一个新的Promise对象,状态为resolved.
let promise = Promise.resolve(123);
promise.then( res => {
console.log(res);
})
由于数字123不属于异步操作(判断方法是该对象是否具有then方法),返回Promise实例的状态resolved,所以回调函数会立即执行,Promise.resolve()方法的参数,会同时传给回调函数。
- 不带有任何参数
Promise.resolve()方法允许调用时不带参数,直接返回一个resolved状态的Promise对象,所以,如果希望得到一个Promise对象,比较方便的方法是直接调用Promise.resolve()方法
// promise就是一个Promise对象
let promise = Promise.resolve(123);
promise.then( res => {
})
2.8、Promise.reject()
Promise.reject(err)方法返回一个新的Promise实例对象,该实例的状态为rejected
let promise = Promise.reject('执行过程异常.');
promise.catch( err => {
console.log(err);
})
生成的Promise对象实例,状态为rejected,回调函数会立即执行,但是Promise.reject()方法的参数,会原封不动的作为reject的理由,变成后续方法的参数,与Promise.resolve()方法不同。
2.9、Promise.all()
all()方法的参数都是promise对象,all()方法中是把所有的peomise实例对象打包,放进一个数组中去,打包完还是一个promise对象,如果是all()方法,必须确保所有的promise对象都是resolve状态,都是成功的状态,否则会报错!
let promise1 = Promise.resolve("promise1状态:执行成功");
let promise2 = Promise.resolve("promise2状态:执行成功");
let promise3 = Promise.resolve("promise3状态:执行成功");
Promise.all([promise1,promise2,promise3]).then( res => {
console.log(res);
let [r1,r2,r3] = res;//解构数组
console.log(r1,r2,r3);
})
let promise1 = Promise.resolve("promise1状态:执行成功");
let promise2 = Promise.reject("promise2状态:执行失败");
let promise3 = Promise.resolve("promise3状态:执行成功");
Promise.all([promise1,promise2,promise3]).then( res => {
console.log(res);
})
2.10、Promise.race()
用法和all()差不多,但是唯一区别的是只要最前面一个是resolve成功的就可以了(二者的区别有点像逻辑运算中的 与 运算和 或 运算,只是这个最前面如果是reject就会报错)
let promise1 = Promise.resolve("promise1状态:执行成功");
let promise2 = Promise.reject("promise2状态:执行失败");
let promise3 = Promise.reject("promise3状态:执行失败");
Promise.race([promise1,promise2,promise3]).then( res => {
console.log(res);// 返回成功的状态结果
})
let promise1 = Promise.reject("promise1状态:执行失败"); // 只要最前面是reject就会报错
let promise2 = Promise.resolve("promise2状态:执行成功");
let promise3 = Promise.resolve("promise3状态:执行成功");
Promise.race([promise1,promise2,promise3]).then( res => {
console.log(res);
})