这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战
Promise对象
ECMAScript 6新增了Promise对象,该对象允许对延迟和异步操作流程进行控制。一个Promise对象就是一个代表了异步操作最终完成或者失败的对象。
开发人员可以使用由其他函数创建并返回的Promise 对象。Promise 对象本质上就是一个绑定了回调的对象,而不是将回调传进函数内部。
一个Promise 有以下几种状态:
- pending : 初始状态,既不成功,也不是失败状态。
- fulfilled : 意味着操作成功。
- rejected : 意味着操作失败。
一、创建Promise对象
ECMAScript 6新增了Promise 对象是一个构造函数,用于创建生成Prormise 对象实例。
new Pormise( function(resolve,reject){...}/* executor*/);
executor 表示带有 resolve 和 reject 两个参数的函数。
- Promise 构造函数执行时立即调用 executor 函数,resolve 和 reject 两个函数作为参数传递给 executor (executor 函数在 Promise 构造函数返回新建对象前被调用)。
- resolve 和 reject 函数被调用时, 分别将 Promise 状态改为 fulfilled(完成)或 rejected(失败)。
/*
创建Promise对象
let promise = new Promise(function(resolve,reject){})
* 当前的构造函数Promise接收一个回调函数
function(resolve,reject){}
* resolve - 是一个函数,将Promise的状态改为fulfilled(完成)
* reject - 是一个函数,将Promise的状态改为rejected(失败)
*/
//Promise的初始化状态,既不成功也不失败
let promise = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('测试成功啦');
},200);
});
// then将Promise状态改变 - 要么成功,要么失败
promise.then((value)=>{
console.log(value);
});
// Promise 对象由其他函数创建并返回
function fn() {
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('测试成功啦');
},200);
});
};
var promise1 = fn();
console.log(promise1);
二、Promise 对象的约定
在应用 Promise 时,将会有一下约定:
- 在 javascript 事件队列的当前运行完成之前,回调函数永远不会被调用。
- 通过 .then 形式添加的回调函数,甚至都在异步操作完成之后才被添加的函数,都会被调用。
- 通过多次调用 .then,可以添加多个回调函数,他们回按照插顺序并且独立运行。
因此,Promise 最直接的好处就是链式调用。
三、Promise 对象的链式操作
常见的需求就是连续执行两个或者多个异步操作。这种情况下,每一个后来的操作都在前面的操作执行成功之后,带着上一步操作所返回的结果开始执行。
示例代码如下:
// 创建Promise对象
let promise = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('测试成功啦');
},200);
});
// then()方法返回一个新的promise对象
let promise2 = promise.then((value) => {
console.log(value);
});
console.log(promise === promise2);//false
//promise和promise2是两个Promise对象
四、Promise对象原型的方法
(1)then() 方法
then()方法用于为Promise 对象添加状态改变时回调函数。then()方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。
p.then(function(value){/*fulfillment*/},function(reason){/*rejection*/});
- 第一个回调函数:当Promise变成接受状态 ( fulfillment )时,该参数作为回调函数被调用。该函数有一个参数,即接受的最终结果。
- 第二个回调函数:当Promise 变成拒绝状态( rejection )时,该参数作为回调函数被调用。该函数有一个参数,即拒绝的原因。
(2)catch() 方法
catch()方法返回一个Promise对象,并且处理拒绝的情况。它的行为与调用then()方法相同。
p.catch(function(reason){/*拒绝*/});
- 回调函数:当 Promise 被 rejected 时,将调用该回调函数。该函数具有一个参数,即rejection的原因。
示例代码如下:
// 创建Promise对象
let promise = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject(new Error('测试失败啦...'));
},200);
});
//then()方法 - 当改变你Promise 状态时执行回调函数(成功)
promise.then((value)=>{
console.log('then()方法:'+ value);
}).catch((value)=>{
console.log('catch()方法:'+ value);
});//catch()方法:Error: 测试失败啦...
(3)finally() 方法
finally()方法返回一个Promise对象,在执行then()和catch()后,都会执行 finally 指定的回调函数。避免同样的语句需要在then()和catch()中各写一次的情况。
五、Promise对象的方法
(1)Promise.all() 方法
Promise.all() 方法用于将多个Promise对象,包装成一个新的Prormise 对象。
Promise.all(iteravle);
- iteravle : 一个可迭代对象,如Array 或 String 等。
示例代码如下:
let promise1 = new Promise(()=>{});
let promise2 = new Promise(()=>{});
let promise3 = new Promise(()=>{});
// Promise.all()方法将多个Promise对象整合成一个Promise对象
let promise = Promise.all([promise1,promise2,promise3]);
(2)Promise.race() 方法
Promise.race()方法返回一个Promise 对象,一旦迭代器中的某个 Promise 解决或拒绝,返回的Promise 就会解决或拒绝。
Promise.race(iteravle);
- iteravle : 一个可迭代对象,如Array 或 String 等。
示例代码如下:
let promise1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('one');
},300);
});
let promise2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('two');
},100);
});
let promise3 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('three');
},200);
});
// race()方法是以某个(最快)的Promise对象的状态都改变时,表示整合后的Promise对象成功或失败
Promise.race([promise1,promise2,promise3]).then((value) =>{
console.log(value);//two
});
(3)Promise.resolve() 方法
Promise.resolve() 方法返回一个以给定值解析后的Promise 对象。
Promise.reject(value)
- value:将被Promise 对象解析的参数。也可以是一个Promise 对象或者是一个thenable(即带有
then()方法)。
(4)Promise.reject() 方法
Promise.reject() 方法返回一个带有拒绝原因 reason 参数的 Promise 对象。
Promise.reject(reason)
- reason : 表示 Promise 被拒绝的原因。
六、Promise 对象的应用
(1)加载图片
可以将图片的加载写成一个Promise ,一旦加载完成,Promise 的状态就发生变化。
const preloadlmage = function (path){
return new Promise(function (resolve, reject) {
const image = new Image();
image.onload = resolve;
image.onerror = reject;
image.src = path;
});
};
(2)通过Ajax加载图片
function imgLoad(url){
return new Promise(function (resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = 'blob';
request.onload = function (){
if (request.status === 200){
resolve(request.response);
}else {
reject(Error('error code:' + request.statusText));
}
};
request.onerror = function () {
reject(Error('lt is a network error.');
};
request.send();
});
}
七、Promise 执行流程