轻松上手ES6之Promise

Promise的基础知识

  • Promise是什么?
    Promise是为了解决异步编程中事件模型和回调模式的不足而产生的一种解决方案,在语法上来说,Promise是一个对象(object)。下图中的promiseABC是我创建的一个promise。
    在这里插入图片描述
  • Promise的生命周期
    每个Promise都有它们相应的生命周期,Promise的生命周期刚开始处于进行中(pending),此时Promise的 执行器函数 (此概念在下文会详细讲解)中的操作尚未完成;当操作结束后,Promise会进入到这两个状态中的其中一个:
    ①Fulfilled,代表Promise异步操作成功完成。②Rejected,代表Promise异步操作失败。
    内部属性[[PromiseState]]表示Promise的三种状态,也就是上文说的pending、fulfilled和rejected,但这个属性不暴露在Promise对象上,不能通过console之类的编程方式来查看Promise的状态,只有当Promise的状态改变时,通过 then()catch() 来进行相应的操作。

创建Promise的基本语法

  • 创建新的Promise(创建未完成的Promise)
    用Promise的构造函数来创建新的Promise,构造函数只接收一个参数:执行器(executor)函数。执行器接收两个参数:resolve()函数和reject()函数。执行器成功完成时调用resolve(),反之调用reject()。
    resolve()函数和reject()函数作为形参当然 可以被随意命名,我们只需要知道它们分别指向then中的第一个参数(完成处理函数)和第二个参数(拒绝处理函数)就行了。
    举个栗子:
let promiseABC = new Promise(function(resolve,reject){//这个function就是执行器
	console.log("你好");//成功输出"你好"
	let a = 1
	if(a==1){
		resolve();//这里会触发resolve()函数
	}
	else{
		reject();
	}
})

在这里插入图片描述
在浏览器的控制台我们输入console.log(promiseABC);可以看到promiseABC是一个promise对象,它此时的状态是resolved,代表执行器中的操作被成功执行,然是由于我们没有定义resolve()函数,因此返回了一个undefined。

  • 创建已处理的Promise
    在上文中我们说到,当执行器内的操作结束后,会进入fulfilled状态或rejected状态。因此已处理的Promise要么调用resolve()函数要么调用reject()函数。

使用Promise.resolve()创建一个完成态的的Promise:

let pr = Promise.resolve("炒米粉");
pr.then(function(food){
	console.log(food);//输出"炒米粉"
});

这个Promise被创建后就是已完成的,因此它不存在拒绝状态,它的reject()函数永远不会被调用

使用Promise.reject()创建一个已拒绝的Promise:

let pr = Promise.reject("炒米粉");
pr.catch(function(food){
	console.log(food);//输出"炒米粉"
});

这个Promise被创建后就是已拒绝的,因此它不存在已完成的状态,它的resolve()函数永远不会被调用。

Promise的then()方法和catch()方法

  • then()方法
    所有的Promise对象都有then()方法,它接收两个参数,第一个是当Promise的状态变为fulfilled时要调用的函数,第二个是当Promise的状态变为rejected时要调用的函数。
    所有与异步操作相关的数据都会传递给第一个函数,而当异步操作失败时,所有的错误信息和附加数据都会传递给第二个函数。
    then()的两个参数都是可选的,换句话来说就是它的两个参数都是可缺省的;但如果当执行器的reject()函数被调用时,then()却没有第二个参数,浏览器将会抛出一个错误。像这样:在这里插入图片描述
    因此如果没有特殊情况,最好要给每一个Promise都添加拒绝处理程序,也就是then()的第二个参数。

  • catch()方法
    这个方法相当于只给then传入第二个参数,也就是只传入拒绝处理程序。下面的这两个代码片是等价的。

let pr = new Promise(function(resolve,reject){
	DOSOMETHING……
});
pr.then(null,function(){
	DOSOMETHING……
});
let pr = new Promise(function(resolve,reject){
	DOSOMETHING……
});
pr.catch(function(){
	DOSOMETHING……
});

执行器的一些特性

执行器函数中的代码会被立刻执行,而调用 resolve()函数reject()函数 会触发一个异步操作,异步操作会被最后执行

举个栗子:

let promiseABC = new Promise(function(resolve,reject){
	console.log("你好");
	reject();
});
promiseABC.catch(function(){
	console.log("拒绝函数被中的代码被执行");
});
console.log("你真好");

运行结果:
在这里插入图片描述
如果执行器函数中的代码发生错误,那么会直接调用拒绝函数。

Promise链

Promise可以串联起来以实现更加复杂的异步操作。
举个栗子:

let promiseABC = new Promise(function(resolve,reject){
	console.log("你好");
	resolve();
});
promiseABC.then(function(){
	console.log("炒米粉");
}).then(function(){
	console.log("炒鸡蛋");
});

运行结果:
在这里插入图片描述
上面的代码等价于:

let promiseABC = new Promise(function(resolve,reject){
	console.log("你好");
	resolve();
});
let pr = promiseABC.then(function(){
	console.log("炒米粉");
});
pr.then(function(){
	console.log("炒鸡蛋");
});

Promise链也可以用于捕获错误,做法与上面then()方法的串联一样,在这就不做代码展示了,需要提出来的是,Promise链的末尾最好要留一个拒绝处理程序(可以是有第二个参数的then()函数,也可以是catch()函数)来确保无论在哪个位置发生了错误都能被处理。

Promise链的一个重要特性是能给下游Promise传递数据。
举个栗子:

let promiseABC = new Promise(function(resolve,reject){
	resolve(6);
});
promiseABC.then(function(num){
	console.log(num);
	return num+1;
}).then(function(num){
	console.log(num);
});

运行结果:
在这里插入图片描述
上面的代码中用的是resolve()函数,当然用reject()函数也是能传递数据的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章