Promise了解
Promise含义
Promise是ES6新增的一种异步编程的解决方案.所谓Promise,简单的说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果.从语法上来讲,Promise是一个对象,我们可通过它获取异步操作的消息.Promise提供各种方便进行异步操作处理的统一的API.
Promise的特点:
1.对象的状态不受外界影响
Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)、rejected(已失败).这三种状态只受到异步操作结果的影响,通常通过一异步操作的结果来决定是哪一种状态.
2.一旦状态改变,就不会再变,任何时候得到的结果都保持一致.
Promise对象的状态改变,只有两种可能:从pending(进行中)变为fulfilled(已成功)、从pending(进行中)变为rejected(已失败).只要这两种状况发生,状态就固定不再改变,这时就称为resolved(已定型).如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果.这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去进行监听,是得不到结果的.
Promise一旦建立无法取消,当建立Promise后,它就会立即执行.Promise内部抛出的错误,需要我们通过设置回调函数才能进行读取.当Promise处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成).
Promise使用:
const promise=new Promise(function(resolve,reject){
.....异步操作代码块
if(/* 异步操作成功 */){
resolve(value)
}else{
reject(error);
}
});
promise.then(res=>{
console.log('success')
}).catch(err=>{
console.log('fail')
}).finally(()=>{
...不论是成功还是失败都会执行此处的代码块
})
/*
ES6规定,Promise的创建通过Promise构造函数进行声明.
Promise构造函数接受一个函数作为参数,该函数又存在两个参数分别为resolve和reject.这两个参数都是函数类型,是javascript引擎默认提供的,不需我们自己构建的.
resolve函数用于当Promise对象的状态从'未完成'转变为'成功'(即从pending->resolved,异步操作成功)时调用,通过将异步操作的成功结果作为参数回调出去.
reject函数用于当Promise对象的状态从'未完成'转变为'失败'(即从pending->rejected状态,异步操作失败)时调用,通过将异步操作失败的提示作为参数传递出去.
当Promise实例生成后,我们可以通过then方法和catch方法分别接受成功状态返回的结果和失败状态返回的错误提示信息.finally方法表示无论成功还是失败都将执行的代码块.
*/
异步加载图片案例:
function loadImageAsync(url) {
return new Promise((resolve, reject) => {
const image = new Image();
image.onload = function () {
resolve(image);
};
image.onerror = function () {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
loadImageAsync(
'https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2776943011,3188085605&fm=26&gp=0.jpg',
)
.then((res) => {
document.body.appendChild(res);
})
.catch((err) => {
console.log(err);
});
Promise对象方法
Promise.all()方法
Promise.all()方法用于将多个Promise实例对象组合成一个新的Promise实例,常用于需要同时获取多个Promise实例对象返回值时使用.
Promise.all()方法接收一个数组或具有iterator接口的对象作为参数,若数组元素都是Promise实例对象,则直接进行处理.若不是Promise实例对象,则会先进行转换为Promise实例对象,再进行处理.
Promise.all()方法返回的数据是Promise实例.
let p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('success 1')
},1000)
})
let p2=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('success 1')
},1000)
})
let p3=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('success 3')
},1000)
})
let p=Promise.all([p1,p2,p3]); // 只有所有promise实例对象的状态都是resolve时,p的状态才为resolve状态;若是实例对象中有一个时rejected状态,则p的状态为rejected状态
console.log(p); // 返回结果也是一个Promise实例
Promise.race()方法
Promise.race()方法的作用与Promise.all()方法相同.都是同时调用多个promise实例对象.
不同点在于Promise.race()方法的返回值只受到第一个返回状态的promise实例的影响
即:当有一个实例对象优先返回状态后,Promise.race()方法的状态就固定为这个实例对象的状态,不再受其他实例的影响.
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 3000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('This is Error message...'));
}, 2000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('This is Error message p3...'));
}, 1000);
});
const p = Promise.race([p1, p2,p3]);
p.then(res=>{
console.log(res)
}).catch(err=>{ // 因为p3比p1和p2先返回状态 reject(new Error('This is Error message p3...')),因此p的状态为rejected
console.log(err); // Error: This is Error message p3...
})
Promise.allSettled()方法
Promise.allSettled()
方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只有等到所有这些参数实例都返回结果,不管是fulfilled
还是rejected
,包装实例才会结束该方法返回的新的 Promise 实例,一旦结束,状态总是
fulfilled
,不会变成rejected
。状态变成fulfilled
后,Promise 的监听函数接收到的参数是一个数组,每个成员对应一个传入Promise.allSettled()
的 Promise 实例。当我们不关心异步操作的结果,只考虑这些异步操作是否都已经完成时,使用Promise.allSettled()方法是一个十分有效的解决方法.
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 3000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('This is Error message p2...'));
}, 2000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('This is Error message p3...'));
}, 1000);
});
const p = Promise.allSettled([p1, p2,p3]);
// 使用Promise.allSettled方法的Promise实例状态只能是fulfilled状态(完成)
p.then((res) => console.log(res))
/**
Promise.allSettled()方法返回的结果是一个数组对象;
每个对象都有status属性,该属性的值只可能是字符串fulfilled或字符串rejected。
当实例对象返回的状态是fulfilled时,对象有value属性;rejected时有reason属性,对应两种状态的返回值。
**/
Promise.any()方法
Promise.any()
方法接受一组 Promise 实例作为参数,包装成一个新的 Promise 实例。只要参数实例有一个变成fulfilled
状态,包装实例就会变成优先返回fulfiled状态的实例的fulfilled
状态;如果所有参数实例都变成rejected
状态,包装实例就会变成rejected
状态。
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success 2')
// reject(new Error('This is Error message p1...'));
}, 3000);
});
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
// reject(new Error('This is Error message p2...'));
resolve('success 1')
}, 2000);
});
const p3 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('This is Error message p3...'));
}, 1000);
});
const p = Promise.any([p1, p2, p3]);
p.then((res) => console.log(res)).catch((err) => {
console.log(err);
});
/**
当所有的promise实例都返回rejected状态时,p的状态为rejected->AggregateError: All promises were rejected
当有一个promise实例返回fulfiled状态时,p的状态为最先返回fulfiled状态的实例.
**/
Promise.resolve()方法与Promise.reject()方法
有时需要将现有对象转为 Promise 对象,Promise.resolve()
方法和Promise.reject()方法就起到这个作用。
Promise.resolve()方法转换的Promise'对象状态都是resolved状态
Promise.resolve()
方法的参数分成四种情况。(1)参数是一个 Promise 实例
(2)参数是一个
thenable
对象(3)参数不是具有
then()
方法的对象,或根本就不是对象(4)不带有任何参数
Promise.reject()方法转换的Promise对象状态都是rejected状态.
简单使用:
const p=Promise.resolve('Hello,World');
/** 上述代码等价于
const p=new Promise((resolve)=>{
resolve('Hello,world');
)
**/
p.then(res=>console.log(res)); // Hello,world
const p = Promise.reject('出错了');
/** 上述代码等价于
const p = new Promise((resolve, reject) => reject('出错了'))
**/
p.then(null, function (s) {
console.log(s)
});
// 出错了