自己实现一个Promise库
先看基本使用
const promise = new Promise((resolve, reject) => {
resolve(value)
// or reject(reason)
})
创建Promise时传入的回调函数是立即执行的,所以我们的Promise应该是这样(用ts实现)
function BDuckPromise(fn: (resolve: (value: any) => void, reject: (reason: any) => void) => any) { function resolve(value: any) { } function reject(reason: any) { } fn(resolve, reject); }
每个Promise对象都有三种生命状态:PENDING(未开始)、FULFILLED(已完成)、REJECTED(已失败)。生命状态只能是PENDING => FULFILLED 或者 PENDING => REJECTED 且一旦发生改变不可逆转。此时我们的代码是这样,具有了状态。
enum STATE {
PENDING = 0,
FULFILLED = 1,
REJECTED = 2
} function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) {
let store = null,
state = STATE.PENDING function resolve(value: any): void {
store = value;
state = STATE.FULFILLED;
} function reject(reason: any): void {
store = reason;
state = STATE.REJECTED;
} fn(resolve, reject)
}
一个Promise对象回调中传入的值(value)或者拒因(reason)是在该示例对象的then函数中获取的
promise.then(value => {
console.log(value);
return value + 1
}, reason => {
// ....
})
then具有两个回调函数onfulfilled(用于成功时传递value)、onrejected(用于失败时传递reason)
所以我们then方法大概是长这样子
function BDuckPromise() {
this.then = (onfulfilled, onrejected) => {
if(state === STATE.PENDING) {
return
} if(state === STATE.FULFILLED) {
onfulfilled(store)
return
} if(state === STATE.REJECTED) {
onrejected(store)
return
}
}
}
但是等一下,如果我们写成这个样子当我们调用then的时候就必须要求promise的状态已经发生过改变我们才能获取到value或者reason,这个显然不是我们需要的。但是我们应该要写成什么样呢?分析一下
当我们调用then时候promise仍然处于pending状态时,我们应该怎么将value或者reason在它状态发生改变是传递出去呢?
显然,我们应该在状态发生改变时调用对应的onfulfilled或者onrejected回调。
那么我们就应该在状态为pending时将回调函数都存储起来,一旦状态改变了,就调用这些回调函数,这下就清楚了,应当在resolve或者reject中调用我们的onfulfilled或者onrejected回调
enum STATE {
PENDING = 0,
FULFILLED = 1,
REJECTED = 2
} function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) {
let store = null,
state = STATE.PENDING,
callbacks = []; function resolve(value: any): void {
store = value;
state = STATE.FULFILLED;
callbacks.forEach(callback => {
if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) {
callback.onfulfilled(store)
}
});
callbacks = null
}; function reject(reason: any): void {
store = reason;
state = STATE.REJECTED;
callbacks.forEach(callback => {
if(callback.onrejected && 'function' === typeof callback.onrejected) {
callback.onrejected(store)
}
});
callbacks = null
}; this.then = (onfulfilled, onrejected) => {
if(state === STATE.PENDING) {
callbacks.push({
onfulfilled,
onrejected
})
return
} if(state === STATE.FULFILLED) {
onfulfilled(store)
return
} if(state === STATE.REJECTED) {
onrejected(store)
return
}
};
fn(resolve, reject)
}
then函数是有返回值的,且返回的的是一个新的Promise对象,所以还得改=_=!
const promise1 = new Promise((resolve, reject) => {
resolve(1)
})
// promise2 是一个新的Promise对象
const promise2 = promise1.then(value => {
return value + 1
})
现在改成这样子
this.then = (onfulfilled, onrejected) => {
return new BDuckPromise((_resolve, _reject) => {
if(state === STATE.PENDING) {
callbacks.push({
onfulfilled,
onrejected
})
return
} if(state === STATE.FULFILLED) {
onfulfilled(store)
return
} if(state === STATE.REJECTED) {
onrejected(store)
return
}
});
}
上一个then函数中return的值会传递给下一个then中作为值
const promise1 = new Promise((resolve, reject) => {
resolve(1)
})
// promise2 是一个新的Promise对象
const promise2 = promise1.then(value => {
return value + 1
})
.then(value => {
console.log(value) // 2
})
好吧,接着改=_=
this.then = (onfulfilled, onrejected) => {
return new BDuckPromise((_resolve, _reject) => {
if(state === STATE.PENDING) {
callbacks.push({
onfulfilled,
onrejected,
_resolve,
_reject
})
return
} if(state === STATE.FULFILLED) {
const ret = onfulfilled(store)
_resolve(ret)
return
} if(state === STATE.REJECTED) {
const ret = onrejected(store)
_reject(ret)
return
}
});
} // 相应的resolve, reject也做相应的更改
function resolve(value: any): void {
store = value;
state = STATE.FULFILLED;
callbacks.forEach(callback => {
if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) {
const ret = callback.onfulfilled(store)
callback._resolve(ret)
}
})
} function reject(reason: any): void {
store = reason;
state = STATE.REJECTED;
callbacks.forEach(callback => {
if(callback.onrejected && 'function' === typeof callback.onrejected) {
const ret = callback.onrejected(store)
callback._reject(ret)
}
})
}
如果then中return的是一个新的Promise则下一个then中的value或reason是这个返回的Promise中resolve或者reject中传递value或者reason
enum STATE {
PENDING = 0,
FULFILLED = 1,
REJECTED = 2
} function BDuckPromise(fn: (resolve:(value: any) => void, reject: (reason: any) => void) => any) {
let store:any = null,
state = STATE.PENDING,
callbacks:any = [] function resolve(value: any): void {
setTimeout(() => {
state = STATE.FULFILLED;
// value 是一个Promise对象
if(value && 'object' === typeof value && value.then && 'function' === typeof value.then) {
// do then
value.then(resolve, reject)
return
}
// value 不是Promise对象
store = value;
callbacks.forEach(callback => {
if(callback.onfulfilled && 'function' === typeof callback.onfulfilled) {
const ret = callback.onfulfilled(store)
callback._resolve(ret)
}
})
callbacks = []
})
} function reject(reason: any): void {
setTimeout(() => {
state = STATE.REJECTED;
// value 是一个Promise对象
if(reason && 'object' === typeof reason && reason.then && 'function' === typeof reason.then) {
reason.then(resolve, reject)
return
}
// value 不是Promise对象
store = reason;
callbacks.forEach(callback => {
if(callback.onrejected && 'function' === typeof callback.onrejected) {
const ret = callback.onrejected(store)
callback._reject(ret)
}
})
callbacks = []
}, 0)
} this.then = (onfulfilled, onrejected) => {
return new BDuckPromise((_resolve, _reject) => {
if(state === STATE.PENDING) {
callbacks.push({
onfulfilled,
onrejected,
_resolve,
_reject
})
return
} if(state === STATE.FULFILLED) {
const ret = onfulfilled(store)
_resolve(ret)
return
} if(state === STATE.REJECTED) {
const ret = onrejected(store)
_reject(ret)
return
}
});
} fn(resolve, reject)
}
export default BDuckPromise;
还有reject的处理,目前是不合规范的
大概就是这样,不搞了
自己实现一个Promise库的更多相关文章
- 小而美的Promise库——promiz源码浅析
背景 在上一篇博客[[译]前端基础知识储备--Promise/A+规范](https://segmentfault.com/a/11...,我们介绍了Promise/A+规范的具体条目.在本文中,我们 ...
- 一步一步实现基于Task的Promise库(一)Promise的基本实现
如果我们现在有一个需求,大概是先读取一个文件的内容,再把得到的内容传给后台去解析,最后把解析后的结果再保存到那个文件,按照最原始的做法代码就是下面这个样子的: //读取文件的原始内容 var read ...
- Promise原理讲解 && 实现一个Promise对象 (遵循Promise/A+规范)
1.什么是Promise? Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一 2.对于几种常见异步编程方案 回调函数 事件监听 发布/ ...
- node.js的Promise库-bluebird示例
前两天公司一哥们写了一段node.js代码发给我,后面特意提了一句“写的不太优雅”.我知道,他意思是回调嵌套回调,因为当时比较急也就没有再纠结.然而内心中总记得要解决这个问题.解决node.js的回调 ...
- 一步一步实现一个Promise A+规范的 Promise
2015年6月,ES2015(即ES6)正式发布后受到了非常多的关注.其中很重要的一点是 Promise 被列为了正式规范. 在此之前很多库都对异步编程/回调地狱实现了类 Promise 的应对方案, ...
- 基于PromiseA+规范实现一个promise
实现如果下规范的promise Aplus规范 1,promise是一个类:有三个状态 pending/等待态 fulfilled/成功态 rejected/失败态 2,promise默认执行器立即执 ...
- 【转载】写一个js库需要怎样的知识储备和技术程度?
作者:小爝链接:https://www.zhihu.com/question/30274750/answer/118846177来源:知乎著作权归作者所有,转载请联系作者获得授权. 1,如何编写健壮的 ...
- 创建你的第一个JavaScript库
是否曾对Mootools的魔力感到惊奇?是否有想知道Dojo如何做到那样的?是否对jQuery感到好奇?在这个教程中,我们将了解它们背后的东西并且动手创建一个超级简单的你最喜欢的库. 我们其乎每天都在 ...
- 教你一步一步实现一个Promise
Promise我想现在大家都非常熟悉了,主要作用就是解决异步回调问题,这里简单介绍下. Promise规范是CommonJS规范之一,而Promise规范又分了好多种,比如 Promises/A.Pr ...
随机推荐
- 最全的iOS物理引擎demo
概述 最全的iOS物理引擎demo,实现重力.碰撞.推力.摆动.碰撞+重力.重力弹跳.仿摩拜单车贴纸效果.防iMessage滚动效果.防百度外卖首页重力感应等效果! 详细 代码下载:http://ww ...
- RBAC权限管理(转)
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用户-角色- ...
- C++:模板友元
模板友元函数在类内声明类外定义时都必须加模板前缀,另外模板要写在一个文件内 // generates undefined error for the operator<< function ...
- SMBUS的介绍与访问
博文是为了总结自己在bios学习上面的点点滴滴,并且加深印象,由于本人水平有限,难免存在不足之处,望指正,同时感谢CSDN提供的平台.本文主要介绍的是SMBUS. 1 SMBUS的简介 特点: SM ...
- JVM基础学习之类的加载、链接和初始化
本文我们一起讨论Java类的加载.链接和初始化. Java字节代码的表现形式是字节数组(byte[]),而Java类在JVM中的表现形式是 java.lang.Class类 的对象.一个Java类从字 ...
- 解决在eclipse中配置Tomcat时,出现"Cannot create a server using the selected type"的错误
比如说使用tomcat 这是因为你之前创建过一次,比如说tomcat6,你指定的目录是:D:/tomcat-6.0.3 后来因为某种原因你把tomcat删了,然后你又安装到了E:/tomcat-6.0 ...
- 启动BusyBox内建的FTP Server
启动BusyBox内建的FTP Server 要启动BusyBox内建的FTP Server,我们需要先孰悉tcpsvd与ftpd这两个命令. tcpsvd可以建立TCP socket,并将它bi ...
- C51寄存器详解(Reg51.h)
Reg51.h 这个头文件将C程序中能用到的寄存器名或寄存器中某位的名称与硬件地址值做了对应,在程序中直接写出这些名称,集成开发环境就能识别,并最终转换成机器代码,实现对单片机各硬件资源的准确操控. ...
- 百度echarts数据报表统计
http://echarts.baidu.com/ http://www.hcharts.cn/demo/index.php?p=13
- SSIS 自测题-控制流控件类
说明:以下是自己的理解答案,不是标准的答案,如有不妥烦请指出. 有些题目暂时没有答案,有知道的请留言,互相学习,一起进步. 62.描述一下 Execute SQL Task 的作用,在 ...