我不知道的Promise(上)

89 阅读4分钟

一、什么是Promise

没想一下这样一个场景:我走到快餐店的柜台,点了一个芝士汉堡,我交给收银员14元。通过下订单并付款,我已经发出了一个对某个值 (就是那个汉堡),的请求。我已经启动了一次交易。但是,通常我不能马上就得到这个汉堡。收银员会交给我某个东西来代替汉堡:一张带有订单号的收据。订单号就是一个承诺 (promise),保证了最终我会得到我的汉堡。

上面这个例子来自 《你不知道的JavaScript》 ,不难看出Promise确保了我们最终能得到一个悬而未决的事情的结果。光说可能有点抽象,那么我们可以通过代码中的具体例子来说明。

1.1 回调地狱

setTimeout(() => {
	// 1层回调
	console.log("延迟1秒后输出");
	setTimeout(() => {
		// 2层回调
		console.log("延迟2秒后输出");
		setTimeout(() => {
			// 3层回调
			console.log("延迟3秒后输出");
		}, 3000);
	}, 2000);
}, 1000);

以上这段代码第一层setTimeout的回调函数中嵌套了第二层setTimeout,而第二层的回调函数又嵌套了第三层setTimeout,这样的层层嵌套会让代码变得不易阅读、难以维护。这种回调函数里面嵌套回调函数的写法,就叫做回调地狱

1.2 如何解决

我们希望能有一种代码组合方式,在确保拿到上一次回调结果并对其进行处理的同时,避免回调地狱引起代码的不断缩进,链式调用是一种很好地解决方式。

doSomething(args).then((result)=>{
    //continue to do something
    return res
}).then((result)=>{
    //continue to do something
    return res
}).then((result)=>{
    //continue to do something
})

以上这段代码中then的回调函数接受了上一次函数调用的返回结果,进行处理后可以将结果继续返回交给下一层then继续处理,代码的简洁性和可读性较之前均有了明显的提升。

1.3 简单介绍

我们今天的主角promise,就是这样一个可以将异步操作队列化按照期望的顺序执行返回符合预期的结果,并且可以在对象之间传递和操作数据,处理队列的一种异步编程的解决方案。

二、Promise的创建

现在我们正式进入对promise的使用阶段。

2.1 Promise的constructor

let promise = new Promise((resolve, reject) {
  // executor(生产者代码,比如load资源)
});
  1. new Promise接受一个函数作为参数,这个函数被称为executor,当new Promise被创建,executor就会自动执行
  2. 这个函数的参数 resolve 和 reject,作为任务完成或失败后的回调函数:
    • resolve(value):如果完成了任务,就如此调用resolve,它会返回成功的value;
    • reject(reason):如果因为任何原因未完成任务,就如此调用reject,它会带上失败的reason。

2.2 Promise的状态变化

new Promise构造器返回的promise对象,具有如下三个状态(state):

  1. pendding(等待态)
  2. rejected(失败态)
  3. fullfilled(成功态)

值得注意的是,状态一旦改变就不会再次变化,就是说一旦promise对象的状态从pendding变为rejected或者fullfilled后无论怎么进行后续操作,状态都不会回到pendding。

2.3 Promise的实例方法

创建Promise实例对象

const p = new Promise((resolve,reject)=>{
            if("异步请求成功"){
                resolve('成功的结果')
            }else{
                reject('失败的信息')
            }
        });
  1. then方法

then接受两个函数分别作为resolve/reject后的回调函数。

 p.then(
     (res)=>{
         //执行resolve则进入此函数
         console.log(res) //成功的结果
     },
     (err)=>{
         //执行reject则进入此函数
         console.log(err) //失败的信息
     }
 )
  1. catch方法

catch接受一个函数作为reject或者抛出错误后的回调函数。
注:catch实际上是then(undefined,(err)=>{})的语法糖,等价于不传入resolve的回调函数只传入reject的回调函数。

p.catch(
    //捕获错误
    //reject或throw一个error后会被catch捕获
    (err)=>{
        console.log(err) //错误的信息
    }
)
  1. finally方法

finally接受一个函数作为最后必定执行的回调函数。
注:finally将result或者error直接传递给下一个处理程序,而不是像then那样自己返回一个thenable对象。

 p.then(
     (res)=>{
         //执行resolve则进入此函数
         console.log(res) //成功的结果
     }
 ).catch(
    //捕获错误
    //reject或throw一个error后会被catch捕获
    (err)=>{
        console.log(err) //错误的信息
    }
).finally(
    (finally)=>{
        console.log(finally) //最后必定执行的代码
    }
)

以上就是Promise的基本介绍和三个实例方法的说明。