Promise的源码实现(符合Promise/A+规范)
我们手写一个Promise/A+规范,然后安装测试脚本,以求通过这个规范。
//Promise/A+源代码
// new Promise时,需要传递一个executor执行器,执行器立即执行
// executor接受两个参数,分别是resolve和reject
// promise只能从pending到rejected,或者从pending到fulfilled
// promise的状态一旦确认,就不会再改变
// promise有then方法,then接受两个参数,分别是promise成功的回调onFulfilled
// 和promise失败的回调 onRejected
// 如果调用then时,promise已经成功,则执行onFulfilled,并将promise值作为参数传递进去
// 如果promise已经失败,那么执行onRejected并把promise失败的原因作为参数传递进去
// 如果promise状态是pending,需要将onFulfilled和onRejected函数存放起来,等待状态确定后,再一次将对应的函数执行(发布)
// then的参数onFulfilled和onRejected可以缺省
// promise可以then多次,promise的then方法返回一个promise
// 如果then返回的是一个结果,那么就把这个结果作为参数,传递给下一个then的成功的回调onFulfilled
// 如果then中抛出了异常,那么就会把这个异常作为参数,传递给下一个失败的回调 onRejected
// 如果then返回的是一个promise,那么需要等这个promise,那么会等这个promise执行完,promise如果成功
// 就走下一个then的成功,如果失败,就走下一个then的失败
//pending状态,可以认为是一种中间状态
const PENDING = 'pending';
// fullfilled完成状态,可以认为是成功回调了的状态
const FULFILLED = 'fullfilled';
// reject即为拒绝状态,即失败的状态
const REJECTED = 'reject';
// executor是一个执行器
function Promise(executor){
let self = this;
self.status = PENDING;
self.onFulfilled = [];//成功的回调
self.onRejected = [];//失败的回调
// PromiseA+ 2.1
function resolve(value){
if(self.status === PENDING){
self.status = FULFILLED;
self.value = value;
self.onFulfilled.forEach(fn=>fn());//PromiseA+ 2.2.6.1
}
}
function reject(reason){
if(self.status===PENDING){
self.status = REJECTED;
self.reason = reason;
self.onRejected.forEach(fn=>fn());//PromiseA+ 2.2.6.2
}
}
try{
executor(resolve,reject)
}catch(e){
reject(e)
}
}
// then必须返回一个promise
Promise.prototype.then = function(onFulfilled,onRejected){
// PromiseA+ 2.2.1/PromiseA+ 2.2.5/PromiseA+ 2.2.7.3/PromiseA+2.2.7.4
onFulfilled = typeof onFulfilled ==='function'?onFulfilled:value =>value;
onRejected = typeof onRejected === 'function'?onRejected:reason=>{throw reason};
let self = this;
//PromiseA+ 2.2.7
let Promise2 = new Promise((resolve,reject)=>{
if(self.status===FULFILLED){
//PromiseA+2.2.2
// Promise A+2.2.4----setTimeout
setTimeout(()=>{
try{
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
//PromiseA+2.2.7.2
reject(e)
}
});
}else if(self.status === REJECTED){
// PromiseA+ 2.2.3
setTimeout(()=>{
try{
let x = onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
})
}else if(self.status===PENDING){
self.onFulfilled.push(()=>{
setTimeout(()=>{
try{
let x = onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
}catch(e){
reject(e);
}
});
});
}
});
return promise2;
}
function resolvePromise(promise2,x,resolve,reject){
let self = this;
//PromiseA+ 2.3.1
if(promise2===x){
reject(new TypeError('changing cycle'));
}
if(x && typeof x ==="object"|| typeof x ==='function'){
let used;//PromiseA+ 2.3.3.3.3//只能调用一次
try{
let then = x.then;
if(typeof then === 'function'){
//PromiseA+2.3.3
then.call(x,(y)=>{
// PromiseA+ 2.3.3.1
if(used)return;
used = true;
resolvePromise(promise2,y,resolve,reject);
},(r)=>{
//PromiseA+2.3.3.2
if(used)return;
used = true;
reject(r)
});
}else{
//PromiseA+ 2.3.3.4
if(used)return;
used = true;
reject(x);
}
}catch(e){
//PromiseA+ 2.3.3.2
if(used)return;
used = true;
reject(e);
}
}else{
//PromiseA+ 2.3.3.4
resolve(x);
}
}
module.exports = Promise;
我们可以用专门的测试脚本测试所编写的代码是否符合PromiseA+的规范。
在上面的promise实现的代码中,增加一下代码
Promise.defer = Promise.deferred = function(){
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
安装测试脚本
npm install -g promises-aplus-tests
如果当前的promise源码的文件名为promise.js
那么在对应的目录执行以下命令:
promises-aplus-tests promise.js
promises-aplus-tests中共有872条测试用例。以上代码,可以完美通过所有用例。
本文借鉴自:https://blog.csdn.net/liuyan19891230/article/details/88385973
这篇博客是ES6的写法:https://blog.csdn.net/weixin_41436338/article/details/79806033
有空就多学多看源码,你看那么多人那么牛逼啊
Promise的源码实现(符合Promise/A+规范)的更多相关文章
- Promise的源码实现(完美符合Promise/A+规范)
Promise是前端面试中的高频问题,我作为面试官的时候,问Promise的概率超过90%,据我所知,大多数公司,都会问一些关于Promise的问题.如果你能根据PromiseA+的规范,写出符合规范 ...
- JS魔法堂: Native Promise Only源码剖析
一, 前言 深入学习Promise的朋友应该都看过<深入理解Promise五部曲>这一系列的文章, 以解除回调地狱之外的观点来剖析Promise更多的内涵,确实十分精彩. Part 1: ...
- promise/bluebird源码
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/bluebirdsource 本博客同步在http://www.cnb ...
- 异步解决方案promise及源码实现
js语言的特性,造就了特别的异步处理方式,我记得以前用的最多的就是回调函数,那个时候写jquery的ajax时候,特别喜欢写这种代码: $.ajax({ method:'get', url:" ...
- Django day24 cbv和APIView的源码分析 和 resful的规范
一:cbv的源码分析 1.CBV和FBV的区别: - Class Base View CBV(基于类的视图) - Function Base View FBV(基于函数的视图) 2.as_vi ...
- [编织消息框架][netty源码分析]9 Promise 实现类DefaultPromise职责与实现
netty Future是基于jdk Future扩展,以监听完成任务触发执行Promise是对Future修改任务数据DefaultPromise是重要的模板类,其它不同类型实现基本是一层简单的包装 ...
- jQuery之Deferred源码剖析
一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...
- jquery源码解析:jQuery延迟对象Deferred(工具方法)详解2
请接着上一课继续看. $.Deferred()方法中,有两个对象,一个是deferred对象,一个是promise对象. promise对象有以下几个方法:state,always,then,prom ...
- promise源码解析
前言 大部分同学对promise,可能还停留在会使用es6的promise,还没有深入学习.我们都知道promise内部通过reslove.reject来判断执行哪个函数,原型上面的then同样的,也 ...
随机推荐
- Kindle电子书制作
text.html: <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv=& ...
- Largest Rectangle in a Histogram /// 单调栈 oj23906
题目大意: 输入n,,1 ≤ n ≤ 100000,接下来n个数为每列的高度h ,0 ≤ hi ≤ 1000000000 求得最大矩阵的面积 Sample Input 7 2 1 4 5 1 3 34 ...
- Linux用户管理 (3)
用户管理 1 用户添加 基本语法 useradd [选项] 用户名 添加一个用户: 注意事项 1)当用户创建成功后,会自动的创建和用户同名的家目录 2)也可以通过 useradd -d 指定目录 新的 ...
- vim的个性化配置(方便编程)
在用户主目录下新建vimrc即可.例如: vim ~/.vimrc 然后复制进去即可. 配置如下: "关闭vim一致性原则 set nocompatible "显示行号 set ...
- css正則匹配、模糊匹配
//所有class包含font-red的p标签 p[class~="font-red"] {color: red;} [abc^="def"] 选择 abc 属 ...
- VS2010-MFC(对话框:设置对话框控件的Tab顺序)
转自:http://www.jizhuomi.com/software/158.html 上一讲为“计算”按钮添加了消息处理函数后,加法计算器已经能够进行浮点数的加法运算.但是还有个遗留的小问题,就是 ...
- Java-JPA:JPA
ylbtech-Java-JPA:JPA JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对 ...
- 2019 西电ACM校赛网络赛 题解
今年题目难度有较大提升,总体与往年类似,数学题居多.以下为我通过的部分题解. 赛题链接:http://acm.xidian.edu.cn/contest.php?cid=1053 A - 上帝视角 我 ...
- 07_jQuery对象初识(五)事件(非常重要)
1. 目前为止学过的绑定事件的方式 1. 在标签里面写 onclick=foo(this); 2. 原生DOM的JS绑定 DOM对象.onclick=function(){...} 3. jQuery ...
- 理解JWT
1. JSON Web Token是什么 JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的.自包含的方式,用于作为JSON对象在各方之间安全地传输信息.该 ...