PromiseA+规范解读和手promise写部分代码

PromiseA+规范是什么?

Promises/A+为js的promise提供了一个开放的、可靠的、可互操作的JavaScript标准
Promise表示异步操作的最终结果,与promise交互的方式是通过其then方法,该方法注册回调以接收promise的最终值或promise无法实现的原因。
PromiseA+规范官网:https://promisesaplus.com/。

  • Promise是ES6中的内置类,是用来解决异步编程【比如数据请求】的,但是兼容性很差
  • 从PromiseA+规范来讲,拥有then方法的实例对象[/函数]是promise

不带then链的基础版promise:

(function() {
   "use strict"
   /*自定义Promise类*/
   function Promise(executor) {
       let self = this,
           change = null;
       //Promise函数必须是new执行,【当前对象必须是Promise的实例】
       if (!(self instanceof Promise)) throw new TypeError("undefined is not a promise!");
       //executor:必须是一个函数
       if (typeof executor !== "function") throw new TypeError(`Promise resolver ${executor} is not a function !`);
       // 实例具备的属性
       self.PromiseState = "pending";
       self.PromiseResult = undefined;
       self.onFulfilledCallback = []; //成功的回调函数集合
       self.onRejectedCallback = [];  //失败的回调函数集合
       // 修改实例的状态和结果
       change = function change(state, result) {
       		// state :传入的实例的状态
       		//result :传入的实例的值
           //只有状态是pending才可以改变为其他状态
           if (self.PromiseState !== "pending") return;
           self.PromiseState = state;
           self.PromiseResult = result;
          // 根据传入的实例的状态,判断需要执行的回调函数集合
           var callbacks = state === "fulfilled" ? self.onFulfilledCallback : self.onRejectedCallback,
               i = 0,
               len = callbacks.length,
               callback;
            // 创建异步微任务,通知集合中存储的方法执行【前提是集合不为空】
           if (callbacks.length > 0) {
               setTimeout(function() {
                   for (; i > len; i++) {
                       callback = callbacks[i];
                       if (typeof callback === "function") callback(result);
                   }
               }, 0);
           };
       };
       //new Promise()的时候会立即执行executor函数
       try {
           executor(function resolve(result) {
               change("fulfilled", result);
           }, function reject(reason) {
               change("rejected", reason);
           });
       } catch (error) {
           // executor函数执行报错也会使状态变成失败
           change("rejected", error);
       };
       // try catch一般情况下是捕捉不到异步的错误的
   };
   // 构造函数原型
   Promise.prototype = {
       constructor: "Promise",
       wendy: true,
       catch: function() {},
       finally: function() {},
       then: function(onFulfilled, onRejected) {
           // queueMicrotask可以创造一个“异步的微任务”,但是兼容性差;可以基于定时器创造一个异步宏任务,来模拟异步微任务
           var self = this;
           switch (self.PromiseState) {
               // 情况1:如果已经知道对应promise的状态是成功或者失败了,则创建一个“异步微任务”,后期执行[onFulfilled/onRejected]
               case "fulfilled":
                   // 用定时器模拟异步微任务
                   setTimeout(function() { onFulfilled(self.PromiseState) }, 0)
                   break;
               case "fulfilled":
                   setTimeout(function() { onRejected(self.PromiseState) }, 0);
                   break;
               default:
                   // 情况2:如果此时还不知道实例状态,就先把[onFulfilled/onRejected]存储起来,后期更改其状态后,再通知方法执行即可,也是异步微任务
                   self.onFulfilledCallback.push(onFulfilled);
                   self.onRejectedCallback.push(onRejected);
           }
       }
   };
   //支持Symbol再加上类型判断依据属性
   if (typeof Symbol !== "undefined") Promise.prototype[Symbol.toStringTag] = "Promise";
   //普通对象:私有静态方法
   Promise.all = function() {};
   Promise.reject = function() {};
   Promise.resolve = function() {};
   Promise.allSettled = function() {};
   Promise.any = function() {};
   Promise.race = function() {};
   /*暴露API*/
   if (typeof window !== "undefined") window.Promise = Promise; // window
   if (typeof module === "object" && typeof module.exports === "object") module.exports = Promise; //node
})();
let p1 = new Promise(function executor(resolve, reject) {
    resolve("200");
    // reject("NO");
});
let p2 = p1.then(result => {
    return console.log(result);
}, reason => {
    return console.log(reason);
}); // fulfilled
  • 插件必须写到闭包里面,保证内部变量和数据不被外界污染
  • 自定义一个类并把API(接口)名称暴露出去:
    • 暴露给window
    • 暴露给一些基于node操作的框架
  • Promise必须传入一个函数【executor】,且必须用new执行,否则就报错
  • executor函数必须传入两个函数参数resolve, reject
    • resolve:把promise状态修改成fulfilled,并把传入的值传递给resolve
    • rejected:把promise状态修改成rejected,并把传入的值传递给rejected
    • 如果executor函数执行报错,也会触发rejected函数执行,返回值是报错的原因
    • promise状态只有是pending是才可以转换成其他状态,一旦被修改,就不再改变。
  • new Promise()的时候会立即执行executor函数
    • 如果已经知道对应实例的状态是成功或者失败了,则创建一个异步微任务,后期执行[onFulfilled/onRejected]
    • 如果此时还不知道实例状态,就先把[onFulfilled/onRejected]存储起来,后期更改其状态后,再通知方法执行即可,也是异步微任务
  • 执行change函数:
    • 改变promise的状态:判断promise状态是不是pending,如果不是pending,则不再改变
    • 判断promise的状态,根据状态的成功或者失败,通知对应的集合[ onFulfilledCallbacks / onRejectedCallbacks ] 中存储的方法执行【创建异步微任务,且前提是集合不为空】
  • ES6中的queueMicrotask可以创造一个异步的微任务,但是兼容性差;可以基于定时器创造一个异步宏任务,来模拟异步微任务
  • 创建then方法:
    • 都会接受两个函数参数 [onFulfilled / onRejected] (方法)
    • 并且会返回一个“全新的Promise实例” -> then链
  • 执行then方法,首先要判断当前实例状态是成功或者失败:
    • 如果已经知道对应实例的状态是成功或者失败了,则创建一个异步微任务,后期执行[onFulfilled/onRejected]
    • 如果此时还不知道实例状态,就先把[onFulfilled/onRejected]存储到对应的[ onFulfilledCallbacks / onRejectedCallbacks ] 集合中

相互回调函数处理的模式

【回调函数executor中嵌套[resolve, reject]函数】

  • 回调函数:把一个函数executor作为值,传递到另一个执行的函数Promise中,在Promise中可以把executor执行
    • 执行0~n 次
    • 改变函数中的this
    • 还可以给回调函数传递参数(例如:[resolve, reject]函数)
    • 接收函数的返回值
    • ……

THEN链机制处理

  • 每一次执行then都会返回一个“全新的promise实例【@TP】”【THEN链】
  • 实例状态是由上个then中传入的[onFulfilled/onRejected]任一方法执行结果决定的,看方法执行后的返回值 :
    • 如果返回的不是Promise实例:
      • 方法执行不报错,新实例的状态就是fulfilled,并且return的结果是新实例的结果
      • 方法执行报错,新实例就是失败的,结果是失败的原因【新实例的结果就是失败的】
    • 如果返回的也是一个Promise实例【@RP】:
      • 则【@RP】的状态和结果直接影响了【@TP】的状态和结果。
  • promise的穿透【顺延】
/*自定义Promise类*/
(function(){
function Promise(executor) {/*...*/};
// 校验是否为Promise实例
function isPromise(x) {
 if (x == null) return false; //传入的x是null或者undefined则返回false
 if (/^(object|function)$/i.test(typeof x)) {
     // promise必须是一个函数或者对象
     if (typeof x.then === "function") return true;
     // promise必须有then方法
 };
 return false;// x 不是对象或者函数的返回false
};
// 处理onFulfilled或者onRejected方法执行的返回结果的处理
function handle(newPromise, x, resolve, reject) {
//x不能是新创建的promise实例
 if (x === newPromise) throw new TypeError("Chaining cycle detected for promise #<Promise>");
 //x必须是一个promise实例
 if (isPromise(x)) {
     try {
         x.then(resolve, reject);
     } catch (error) {
         reject(error);
     };
     return;
 };
 // 如果返回的不是promise实例,且没有报错,则promise实例是成功的,x是结果
 resolve(x);
}
Promise.prototype = {
	//...,此处只真是then函数相关代码,其余代码省略
    then: function(onFulfilled, onRejected) {
         var self = this,
             newPromise, //创建一个新的promise实例,并返回该promise实例。
             x; //方法执行的返回结果
         
         //onFulfilled不传值的情况下默认返回一个成功的promise
         if (typeof onFulfilled !== "function") {
             onFulfilled = function onFulfilled(result) {
                 return result;
             };
         };
		
		//onRejected不传值的情况下默认返回一个失败的promise
         if (typeof onRejected !== "function") {
             onRejected = function onRejected(reason) {
                 throw reason;
             };
         };
         
         //resolve & reject 可以设置返回的@TP(新promise实例)是成功还是失败以及结果等
         // 但是执行哪个方法,由要监听onFulfilled|onRejected方法报错和返回值来决定。
         newPromise = new Promise(function(resolve, reject) {    
         	//执行不报错则根据返回的结果来处理返回的promise实例   
         	// 执行报错执行reject,返回的是报错信息。 
             switch (self.PromiseState) {
                 case "fulfilled":
                     setTimeout(function() {
                         try { 
                             x = onFulfilled(self.PromiseResult);
                             handle(newPromise, x, resolve, reject);
                         } catch (error) {
                             reject(error); 
                         };
                     }, 0)
                     break;
                 case "rejected":
                     setTimeout(function() {
                         try {
                             x = onRejected(self.PromiseResult);
                             handle(newPromise, x, resolve, reject);
                         } catch (error) {
                             reject(error);
                         };
                     }, 0);
                     break;
                 default:
                 //类似bind机制,
                 //为了保证方法执行时,方法的上级上下文是当前上下【这样才能获取到当前上下文中的变量】,把需要操作的事情放到一个匿名函数中,把匿名函数传递给onFulfilledCallbacks | onRejectedCallbacks。
                 //依然需要处理执行过程中的报错行为。
                     self.onFulfilledCallbacks.push(function(result) {
                         try {
                             x = onFulfilled(result);
                             handle(newPromise, x, resolve, reject);
                         } catch (error) {
                             reject(error);
                         }
                     });
                     self.onRejectedCallbacks.push(function(reason) {
                         try {
                             x = onRejected(reason);
                             handle(newPromise, x, resolve, reject);
                         } catch (error) {
                             reject(error);
                         }
                     });
             };
         });
         return newPromise;//返回新创建的promise
     };
};
//...
})();

let p1 = new Promise(function executor(resolve, reject) {
    resolve("200");
    // reject("NO");
});
let p2 = p1.then(result => {
    console.log("成功->", result);
    return 10;
}, reason => {
    console.log("失败->", reason);
    return 10;
});

let p3 = p2.then(result => {
    console.log("成功->", result);
    throw "XXX";
}, reason => {
    console.log("失败->", reason);
});
let p4 = p3.then(result => {
    console.log("成功->", result);
}, reason => {
    console.log("失败->", reason);
});
// 成功-> 200
// 成功-> 10
// 失败-> XXX

Promise.resolve

Promise.resolve()返回一个成功的promise实例,返回值是传入的值

Promise.resolve = function(result) {
	return new Promise(function(resolve){
		resolve(result)
	});
};

Promise.reject & Promise.prototype.catch

Promise.reject(reason):返回一个失败的promise,返回值是传入的值
Promise.prototype.catch(onRejected):方法返回一个Promise,并且处理拒绝的情况

Promise.reject = function(reason) {
// _,占位,第一个函数不需要传的时候
	return new Promise(function(_, reject){
		reject(reason);
	});
};

Promise.prototype={
	catch:function(onRejected) {
    	return this.then(null, onRejected);
 	};
}

Promise.all

  • 语法:Promise.all(iterable);
    • iterable: 一个可迭代对象,如 Array 或 String
  • 返回值:只返回一个Promise实例
    • 完成(Fulfillment):结果是按照顺序依次存储每一个promise实例的返回值
      • 当且仅当Promise.all传入的可迭代对象为空时,会同步地返回一个已完成[resolved]状态的promise
      • 传入的 promise 都变为完成状态时,或者传入的可迭代对象内没有 promise,则返回的 promise 异步地变为完成
        • 若参数包含非 promise 值,则忽略,在promise完成后将其放在返回数组中
      • 在任何情况下,Promise.all 返回的 promise 的完成状态的结果都是一个数组,它包含所有的传入迭代参数对象的值(也包括非 promise 值)
    • 失败/拒绝(Rejection):
      • 如果传入的 promise 中有一个失败(rejected),Promise.all 异步地将失败的那个结果给失败状态的回调函数,而不管其它 promise 是否完成。
Promise.all = function(promises) {
   let newPromise = null, //返回的全新的promise实例
       results = [], //成功的promise实例的但返回值的数组
       n = 0; //计数器

   //传入的必须是一个数组 
   if (!(Array.isArray(promises))) throw new TypeError(promises, "is not iterable!");

   //控制集合中的每一项都是promise实例,
   promises = promises.map(function(promise) {
       //不是promise的项变成一个成功的promise实例
       if (!isPromise(promise)) return Promise.resolve(promise);
       return promise;
   });
   // 创建一个全新的promise实例
   newPromise = new Promise(function(resolve, reject) {
       promises.forEach(function(promiseItem, index) {
           promiseItem.then(function(result) {
               //存储的是当前这一项成功的结果,并且保持顺序不变
               results[index] = result;
               //每处理一次,n+1
               ++n;
               // 全部处理成功了,返回成功的promise实例
               if (n >= promises.length) resolve(results);
           }).catch(function(reason) {
               reject(reason); //只要有一项失败,则promise.all返回失败
           })
       });
   });
   return newPromise;// 返回这个全新的promise实例

};
   // ...
let p1 = Promise.resolve(10);
let p2 = new Promise(resolve => {
    setTimeout(() => {
        resolve(20)
    }, 1000)
});
let p3 = 30;

Promise.all([p1, p2, p3]).then(results => {
    console.log("success", results);
}).catch(reason => {
    console.log("fail", reason);
});//success (3) [10, 20, 30]

Promise.prototype.finally()

  • 语法:
    • p.finally(onFinally);
  • 参数:
    • onFinally:Promise 结束后调用的Function。
    • onFinally()函数执行没有参数,并且会把结果和报错信息传递下去
    • 在finally回调中 throw(或返回被拒绝的promise)将以 throw() 指定的原因拒绝新的promise.
  • 返回值:返回一个设置了 finally 回调函数的Promise对象。
  • 在 promise 结束时,无论 Promise 运行成功还是失败,都会运行 finally
Promise.prototype = {
	finally: function(onFinally) {
	    return this.then(function onFulfilled(resolve) {
	        return Promise.resolve(onFinally()).then(function() {
	            return resolve;
	        })
	    }, function onRejected(reason) {
	        return Promise.resolve(onFinally()).then(function() {
	            throw reason;
	        });
	    })
	},
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值