ECMAScript 6新增 Promise对象

310 阅读5分钟

这是我参与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 执行流程

Promise执行流程图正式.png Promise执行流程图.png