Promise规范及应用
Promise规范
术语
- promise 是?个有then?法的对象或者是函数,?为遵循本规范
- thenable是一个有then方法或者是函数
- value是promise状态成功时的值,也就是resolve的参数,包括各种数据类型, 也包括 undefined/thenable 或者是 promise
- reason是promise状态失败的值,也就是reject的参数,表示拒绝的原因
- exception 是一个使用throw抛出的异常值
规范
promise states
Promise应该有三种状态
- pending
- 初始的状态,可改变
- 一个promise在resolve或者reject前都处于这个状态
- 可以通过resolve → fulfilled状态
- 可以通过 reject → rejecteed 状态
- fulfulled
- 最终态,不可改变
- 一个promise被resolve后就会变成这个状态
- 必须拥有一个value值
- rejected
- 最终态,不可改变
- 一个promise被reject后会变成这个状态
- 必须拥有一个reason
promise的状态流转是这样的:
pending → resolve(value) → fulfilled
pending → reject(reason) → rejecteed
then
promise应该提供一个then方法,用来访问最终的结果,无论是value还是reason
promise.then(onFulfilled,onRejected)
-
参数要求
- onFulfilled 必须是函数类型,如果不是函数,应该被忽略
- onRejected 必须是函数类型,如果不是函数,应该被忽略
-
onFulfilled特性
- 在promise变成fulfilled时,应该调用onFulfilled,参数时value
- 在promise变成fulfilled之前,不应该被调用
- 只能被调用一次(所以在实现的时候需要?个变量来限制执?次数)
-
onRejected特性
- 在promise变成rejected时,应该调用onRejected,参数是reason
- 在promise变成rejected之前,不应该被调用
- 只能被调用一次(所以在实现的时候需要?个变量来限制执?次数)
-
onFulfilled和onRejected应该是微任务
- 这里使用queueMicrotask来实现微任务的调用
-
then方法可以被调用多次
- promise状态变成fulfilled后,所有的onFulfilled回调都需要按照then的顺序执行,也就是按照注册顺序执行(所以在实现的时候需要?个数组来存放多个onFulfilled的回调)
- promise状态变成rejected后,所有的onRejected回调都需要按照then的顺序执行,也就是按照注册顺序执行(所以在实现的时候需要?个数组来存放多个onRejected的回调)
-
返回值 then应该返回一个promise newPromise=promise.then(onFulfilled,onRejected);
- onFulfulled或onRejected执行的结果为x,调用resolvePromise
- 如果onFulfilled或者onRejected执行时抛出异常e,newPromise需要被reject
- 如果onFulfilled不是一个函数,newPromise以promise的value触发fulfilled
- 如果onRejected不是一个函数,newPromise以promise的reason触发rejected
-
resolvePromise resolvePromise(newPromise,x,resolve,reject)
-
如果newPromise和x相等,那么 reject TypeError -
如果x是一个promise ? 如果x是pending态,那么promise必须要在pending,直到 x 变成 fulfilled or rejected. ? 如果 x 被 fulfilled, fulfill promise with the same value. ? 如果 x 被 rejected, reject promise with the same reason. -
如果 x 是?个 object 或者 是?个 function let then = x.then. 如果 x.then 这步出错,那么 reject promise with e as the reason. 如果 then 是?个函数,then.call(x, resolvePromiseFn, rejectPromise) ? resolvePromiseFn 的 ?参是 y, 执? resolvePromise(newPromise, y, resolve, reject); ? rejectPromise 的 ?参是 r, reject promise with r ? 如果 resolvePromise 和 rejectPromise 都调?了,那么第?个调?优先,后?的调?忽 略。 ? 如果调?then抛出异常e ? 如果 resolvePromise 或 rejectPromise 已经被调?,那么忽略 ? 则,reject promise with e as the reason ? 如果 then 不是?个function. fulfill promise with x
实现一个promise
初始化
平常?promise的时候, 是通过new关键字来new Promise(),所以应该?构造函数或者class来实现
class MPromise{
constructor(){
}
}
定义三种状态
const PENDING='pending';
const FULFILLED='fulfilled';
const REJECTED='rejected';
设置初始状态
class MPromise{
constructor(){
this.status=PENDING;
this.value=null;
this.reason=null;
}
}
resolve 和 reject方法
这两个?法是要更改status的, 从pending改到fulfilled/rejected.
这两个函数的?参分别是value 和 reason.
class MPromise{
constructor(){
this.status=PENDING;
this.value=null;
this.reason=null;
}
resolve(value){
if(this.status===PENDING){
this.status=FULFILLED;
this.value=value;
}
}
reject(reason){
if(this.status===PENDING){
this.status=REJECTED;
this.reason=reason;
}
}
}
promise的入参应该是个函数
- ?参是?个函数, 函数接收resolve和reject两个参数.
- 注意在初始化promise的时候, 就要执?这个函数, 并且有任何报错都要通过reject抛出去
class MPromise{
constructor(fn){
this.status=PENDING;
this.value=null;
this.reason=null;
try{
fn(this.resolve.bind(this),this.reject.bind(this));
}catch(e){
this.reject(e);
}
}
resolve(value){
if(this.status===PENDING){
this.status=FULFILLED;
this.value=value;
}
}
reject(reason){
if(this.status===PENDING){
this.status=REJECTED;
this.reason=reason;
}
}
}
then方法
1.then接收两个参数, onFulfilled 和 onRejected
then(onFulfilled,onRejected){}
2.检查并处理参数, 之前提到的如果不是function, 就忽略. 这个忽略指的是原样返回value或者reason.
首先判断参数是否是函数类型
isFunction(param){
return typeof param==='function';
}
then
then(onFulfilled, onRejected) {
const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled :(value) => {
return value;
};
const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason)=> {
throw reason
};
}
3.根据promise的状态,调用不同的函数
当在then函数被调?的瞬间就会执?. 那这时候如果status还没变成fulfilled或者rejected怎么办, 很有可能还是pending的
那么我们?先要拿到所有的回调, 然后才能在某个时机去执?他. 新建两个数组, 来分别存储成功和失败的回调, 调?then的时候, 如果还是pending就存?数组.
then(onFulfilled, onRejected) {
const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled :(value) => {
return value;
};
const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason)=> {
throw reason
};
switch(this.status){
case FULFILLED:{
fulFilledFn(this.value);
break;
}
case REJECT:{
rejectedFn(this.reason);
break;
}
case PENDING: {
this.FULFILLED_CALLBACK_LIST.push(realOnFulfilled);
this.REJECTED_CALLBACK_LIST.push(realOnRejected);
break;
}
}
}
class MPromise {
FULFILLED_CALLBACK_LIST = [];
REJECTED_CALLBACK_LIST = [];
_status = PENDING;
constructor(fn) {
this.status = PENDING;
this.value = null;
this.reason = null;
try {
fn(this.resolve.bind(this), this.reject.bind(this));
} catch (e) {
this.reject(e);
}
}
reason(value){}
reject(reason){}
then(onFulfilled, onRejected){
const fulFilledFn = this.isFunction(onFulfilled) ? onFulfilled :(value) => {
return value;
};
const rejectedFn = this.isFunction(onRejected) ? onRejected : (reason)=> {
throw reason
};
switch(this.status){
case FULFILLED:{
fulFilledFn(this.value);
break;
}
case REJECT:{
rejectedFn(this.reason);
break;
}
case PENDING: {
this.FULFILLED_CALLBACK_LIST.push(realOnFulfilled);
this.REJECTED_CALLBACK_LIST.push(realOnRejected);
break;
}
}
}
isFunction(param){
return typeof param==='function';
}
}
在status发?变化的时候, 就执?所有的回调.
get status(){
return this._status;
}
set status(newStatus) {
this._status = newStatus;
switch (newStatus) {
case FULFILLED: {
this.FULFILLED_CALLBACK_LIST.forEach((callback) => {
callback(this.value);
});
break;
}
case REJECTED: {
this.REJECTED_CALLBACK_LIST.forEach((callback) => {
callback(this.reason);
});
break;
}
}
}
then的返回值
如果 onFulfilled 或者 onRejected 抛出?个异常 e ,则 newPromise 必须拒绝执?,并返回拒因 e。
then(onFulfilled,onRejected){
const fulFilledFn=this.isFunction(onFulfilled) ? onFulfilled : (value)=>{
return value;
}
const rejectedFn=this.isFunction(onRejected) ? onRejected : (reason)=>{
throw reason;
}
const fulfilledFnCatch=(resolve,reject,newPromise)=>{
try{
fulFilledFn(this.value);
}catch(error){
reject(error)
}
};
const rejectedFnCatch=(resolve,reject,newPromise)=>{
try{
rejectedFn(this.reason);
}catch(error){
reject(error)
}
}
switch(this.status){
case FULFILLED : {
const newPromise=new MPromise(fulfilledFnCatch);
return newPromise;
}
case REJECTED : {
const newPromise=new MPromise(rejectedFnCatch);
return newPromise;
}
case PENDING : {
const newPromise=new MPromise((resolve,reject)=>{
this.FULFILLED_CALLBACK_LIST.push(()=>fulfilledFnCatch(resolve,reject));
this.REJECTED_CALLBACK_LIST.push(()=>rejectedFnCatch(resolve,reject));
})
return newPromise;
}
}
}
如果 onFulfilled 不是函数且 promise 成功执?, newPromise 必须成功执?并返回相同的值
const fulfilledFnCatch=(resolve,reject,newPromise)=>{
try{
fulFilledFn(this.value);
resolve(this.value);
}catch(error){
reject(error)
}
}
如果 onRejected 不是函数且 promise 拒绝执?, newPromise必须拒绝执?并返回相同的据因。
需要注意的是,如果promise的onRejected执?成功了,newPromise应该被resolve
const rejectedFnWithCatch = (resolve, reject) => {
try {
rejectedFn(this.reason);
if (this.isFunction(onRejected)) {
resolve();
}
} catch (e) {
reject(e);
}
}
如果 onFulfilled 或者 onRejected 返回?个值 x ,则运?resolvePromise?法
then(onFulfilled,onRejected){
const fulFilledFn=this.isFunction(onFulfilled) ? onFulfilled : (value)=>{
return value;
}
const rejectedFn=this.isFunction(onRejected) ? onRejected : (reason)=>{
throw reason;
}
const fulfilledFnCatch=(resolve,reject,newPromise)=>{
try{
if(!this.isFunction(onFulfilled)){
resolve(this.value);
}else{
const x=fulFilledFn(this.value);
this.resolvePromise(newPromise,x,resolve,reject);
}
}catch(e){
reject(e);
}
};
const rejectedFnCatch=(resolve,reject,newPromise)=>{
try{
if(!this.isFunction(onRejected)){
reject(this.reason);
}else{
const x=rejectedFn(this.reason);
this.resolvePromise(newPromise,x,resolve,reject);
}
}catch(e){
reject(e);
}
}
switch(this.status){
case FULFILLED : {
const newPromise=new MPromise((resolve,reject)=>fulfilledFnCatch(resolve,reject,newPromise));
return newPromise;
}
case REJECTED : {
const newPromise=new MPromise((resolve,reject)=>rejectedFnCatch(resolve,reject,newPromise));
return newPromise;
}
case PENDING : {
const newPromise=new MPromise((resolve,reject)=>{
this.FULFILLED_CALLBACK_LIST.push(()=>fulfilledFnCatch(resolve,reject,newPromise));
this.REJECTED_CALLBACK_LIST.push(()=>rejectedFnCatch(resolve,reject,newPromise));
})
return newPromise;
}
}
}
resolvePromise
resolvePromise(newPromise, x, resolve, reject) {
if (newPromise === x) {
return reject(new TypeError("xxxxxxxxxxxxxxxx"));
}
if (x instanceof MPromise) {
x.then(
(y) => {
this.resolvePromise(newPromise, y, resolve, reject);
},
reject
);
} else if (typeof x === 'object' || this.isFunction(x)) {
if (x === null) {
return resolve(x);
}
let then = null;
try {
then = x.then;
} catch (error) {
resolve(error);
}
if (this.isFunction(then)) {
let called = false;
try {
then.call(
x,
(y) => {
if (called) {
return;
}
called = true;
this.resolvePromise(newPromise, y, resolve, reject);
},
(r) => {
if (called) {
return;
}
called = true;
reject(r);
}
)
} catch (error) {
if (called) {
return;
}
reject(error);
}
} else {
resolve(x);
}
} else {
resolve(x);
}
}
onFulfilled 和 onRejected 是微任务
?queueMicrotask包裹执?函数
then(onFulfilled,onRejected){
const fulFilledFn=this.isFunction(onFulfilled) ? onFulfilled : (value)=>{
return value;
}
const rejectedFn=this.isFunction(onRejected) ? onRejected : (reason)=>{
throw reason;
}
const fulfilledFnCatch=(resolve,reject,newPromise)=>{
queueMicrotask(()=>{
try{
if(!this.isFunction(onFulfilled)){
resolve(this.value);
}else{
const x=fulFilledFn(this.value);
this.resolvePromise(newPromise,x,resolve,reject);
}
}catch(e){
reject(e);
}
});
};
const rejectedFnCatch=(resolve,reject,newPromise)=>{
queueMicrotask(()=>{
try{
if(!this.isFunction(onRejected)){
reject(this.reason);
}else{
const x=rejectedFn(this.reason);
this.resolvePromise(newPromise,x,resolve,reject);
}
}catch(e){
reject(e);
}
});
}
switch(this.status){
case FULFILLED : {
const newPromise=new MPromise((resolve,reject)=>fulfilledFnCatch(resolve,reject,newPromise));
return newPromise;
}
case REJECTED : {
const newPromise=new MPromise((resolve,reject)=>rejectedFnCatch(resolve,reject,newPromise));
return newPromise;
}
case PENDING : {
const newPromise=new MPromise((resolve,reject)=>{
this.FULFILLED_CALLBACK_LIST.push(()=>fulfilledFnCatch(resolve,reject,newPromise));
this.REJECTED_CALLBACK_LIST.push(()=>rejectedFnCatch(resolve,reject,newPromise));
})
return newPromise;
}
}
}
catch方法
catch(onRejected){
return this.then(null,onRejected);
}
promise.resolve
将现有对象转为Promise对象,如果 Promise.resolve ?法的参数,不是具有 then ?法的对象(?称 thenable 对象),则返回?个新的 Promise 对象,且它的状态为fulfilled。
static resolve(param) {
if (param instanceof MyPromise) {
return param;
}
return new MyPromise(function (resolve) {
resolve(param);
});
}
promise.reject
返回?个新的Promise实例,该实例的状态为rejected。Promise.reject?法的参数reason,会被传递给实例的回调函数。
static reject(reason) {
return new MPromise((resolve, reject) => {
reject(reason);
});
}
promise.race
const p = Promise.race([p1, p2, p3]);
该?法是将多个 Promise 实例,包装成?个新的 Promise 实例。
只要p1、p2、p3之中有?个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise 实例的返回值,就传递给p的回调函数。
static race(promiseList) {
return new MPromise((resolve, reject) => {
const length = promiseList.length;
if (length === 0) {
return resolve();
} else {
for (let I = 0; I < length; I++) {
MPromise.resolve(promiseList[I]).then(
(value) => {
return resolve(value);
},
(reason) => {
return reject(reason);
});
}
}
});
}
|