Promise规范及其应用

Promise规范及其应用

以下是关于学习promise A+规范的一些心得体会,以及手撕promise、实现一个promise等总结。

一:Promise A+ 规范

规范就是在我们实现的过程中需要遵循的一些规则,可能是比较枯燥但是却是进行理解基础,只有知道了定义此规范的人是如何思考的,才能以不变应万变,应对在开发过程中遇到的各种坑。

以下是一些在规范中提到的术语,了解了这部分术语,有利于我们更加后面的理解学习
  1. promise :是一个有then方法的对象或函数,它的行为遵循promise A+规范;

  2. thenable:也是一个有then方法的对象或者函数;

  3. value :promise状态成功时候的值,也就是promise中resolve的参数;可以是各种数据类型:undefined/number/boolean/promise/string等等,都可。

    const promise = new Promise((resolve, reject) => {
    			// 其中resolve中的参数‘value’就是value,value类型可为上诉任意一种。
                resolve('value')  
            })
    
  4. reason :promise状态失败时的值,也就是reject的参数,表示执行失败(拒绝)的原因;

    const promise = new Promise((resolve, reject) => {
                // 其中reject中的参数‘reason’就是reason。执行失败的原因。
                reject('reason')
            })`
    
  5. exception :异常,抛出去的异常(throw);

promise A+规范(具体规则):

1、promise的状态 status

resolve、reject是动作,(一般是函数);而pending、fulfilled、rejected是状态,是动作的结果。
  1. promise有三种状态:pending、fulfilled、resolved。

  2. pending:promise的初始状态,一个promise刚被初始化出来之后,未执行其他操作,就是pending状态(==》被resolve或者reject之前的状态)。pending状态可改变,可通过resolve变为fulfilled状态;通过reject 变为rejected状态。

  3. fulfilled:一个最终态,不可对其再进行改变;如何变为fulfilled?一个promise经过resolve之后就可以改变;必须拥有一个value值,resolve(value),其中value必选。

    const promise = new Promise((resolve, reject) => {
         // 其中resolve中的参数必选,resolve()其实就相当于传入一个undefined==》等同于resolve(undefined)。
         resolve();
    })
    
  4. rejected:一个最终态,不可对其再进行改变;如何变为rejected?一个promise经过reject之后就可以改变;必须拥有一个reason值,reject(reason),其中reason必选。

    const promise = new Promise((resolve, reject) => {
    	  // 其中reject中的参数必选,reject()其实就相当于传入一个undefined==》等同于reject(undefined)。
    	  reject();
    })
    
    状态流转的过程: 
    		1、pending ---》resolve(value)---》fulfilled;
    		2、pending ---》reject(reason)---》rejected;
    

. 2、then

   1、promise应该提供一个then方法,用来访问最终的结果(无论是value还是reason);常规来说reject(reason)应该是进入catch函数的,但是catch正常执行之后会再返回一个promise,这时这个promise再.then的时候也会去接受到reason---》即只需要再catch中返回reason,啥都不return,相当于return了一个undefined。
   2、then函数可以接受两个参数,promise.then(onFulfilled, onRejected);
  1. then函数的两个参数要求:
    1)、onFulfilled:必须是函数类型,如果不是函数类型,则应该被忽略,(具体如何忽略,见下文)
    2)、onRejected:必须是函数类型,如果不是函数类型,也应该被忽略。(见下文)

  2. onFulfilled特性
    1)promise状态变为fulfilled时,应该调用onFulfilled函数,参数时value。
    2)promise状态变为fulfilled之前,不应该被调用。
    3)只能被调用一次。(需要一个变量来限制执行的次数)

  3. onRejected特性
    1)promise状态变为rejected时,应该调用onRejected函数,参数时reason。
    2)promise状态变为rejected之前,不应该被调用。
    3)只能被调用一次。(需要一个变量来限制执行的次数)

  4. onFulfilled和onRejected应该是微任务,(使用queueMicrotask来实现微任务的调用)

  5. then方法可以被多次调用
    1)promise状态变为fulfilled的时候,所有的onFulfilled的回调函数都应该按照then的顺序来执行;

    伪代码:eg1:promise.then(cb1).then(cb2).then(cb3),回调的执行顺序:cb1、cb2、cb3
    
    eg2:const promise = new Promise((resolve, reject) => {...});
    			promise.then();
    			promise.then();
    	上述伪代码中,可以先new一个promise,然后再同一个promise上面挂载多个then,也算是then方法一直调用的实现。
    	=》多次then调用之后,对应的callback应该怎么存??
    	由于是挂载在同一个promise上,需要一个数组来存储onFulfilled的回调函数,这样可以将多个回调函数存在同一个地方,同时数组可以确定执行的顺序。
    

    2)promise状态变为rejected的时候,所有的onRejected的回调函数都应该按照then的顺序来执行;(这里都用then,因为then可以接受两个参数,第二个表示onRejected,也可省略,即为null);同上,同样需要一个数组来存储。

  6. then的返回值:promise(新的)

    1)onFulfilled或者onRejected函数的执行结果是 x,然后去调用对应的resolvePromise。
    (resolvePromise—》理解:用来真正将promise的状态变更执行的方法(相当于一个底层更改状态的函数—》本人理解,有其他更好的理解欢迎指出!))
    2)onFulfilled或者onRejected执行时抛出异常,promise2(也就是这个新的promise)需要被reject。
    3)如果onFulfilled不是一个函数,promise2就会以promise1的value触发fulfilled—《状态变更为filfilled,接收promise1的value,promise1是啥promise2就是啥》
    4)如果onRejected不是一个函数,promise2就会以promise1的reason触发rejected—《状态变更为rejected,接收promise1的reason,promise1是啥promise2就是啥》

  7. resolvePromise
    resolvePromise(promise2,x,resolve,reject)
    1)如果promise2和 x 相等,则reject TypeError。(因为promise2 和 x 相等的话,会造成死循环)

    2)如果 x 是是一个promise:

    1、如果 x 是pending,(因为一个promise的初始状态必须为pending),则必须等到 x 的状态变为fulfilled或者是rejected。
    2、如果 x 是fulfilled,就不需要等待了,直接将x promise的value透传到外界的promise2中,并且状态更改为fulfilled。
    3、如果 x 是rejected,就不需要等待了,直接将x promise的reason透传到外界的promise2中,并且状态更改为rejected。
    

    3)如果 x 是一个Object 或者 是一个 function:

    1、let then = x.then;  // 会去判断这一步的赋值是否会报错,(如果x.then这一步出错了,try catch(e), 抛出一个错误,那么就直接reject(e))
    2、如果获取到的then是一个函数,则直接以当前的这个 x 去调用即可。 then.call(x, resolvePromiseFn, rejectPromiseFn)
    
    resolvePromiseFn: 入参是y,执行 resolvePromise(promise2, y, resolve, reject);
    这个y就是一个名称而已,取其他的是一样的,其实就是相当于 x 去调用then的时候会有返回的执行结果,就取值为了 y 。
    
    如果调用.then的时候抛出了异常,如果此时的resolvePromiseFn和rejectPromiseFn已经执行完成了,则不用去管这个了; 如果未执行完成,则需要reject 一个reason。
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值