基础功能
class Bromise{
static PENDING = '待定'
static FULFILLED = '成功'
static REJECTED = '失败'
constructor(func){
this.status = Bromise.PENDING
this.result = null
func(this.resolve,this.reject)
}
resolve(result){
if(this.status === Bromise.PENDING){
this.status = Bromise.FULFILLED
this.result = result
}
}
reject(result){
if(this.status === Bromise.PENDING){
this.status = Bromise.REJECTED
this.result = result
}
}
}
let bromise = new Bromise((resolve,reject)=>{
resolve('成功')
})
问题:报错Uncaught TypeError: Cannot read properties of undefined (reading 'status')
原因:类中所有定义的方法,在浏览器运行时候全部都加上了 user strict !
所以第8行的this指向的其实是undefined。
绑定this
解决方法:bind绑定。
class Bromise{
static PENDING = '待定'
static FULFILLED = '成功'
static REJECTED = '失败'
constructor(func){
this.status = Bromise.PENDING
this.result = null
func(this.resolve.bind(this),this.reject.bind(this))
}
resolve(result){
if(this.status === Bromise.PENDING){
this.status = Bromise.FULFILLED
this.result = result
}
}
reject(result){
if(this.status === Bromise.PENDING){
this.status = Bromise.REJECTED
this.result = result
}
}
}
let bromise = new Bromise((resolve,reject)=>{
resolve('成功')
})
实现then方法
class Bromise{
static PENDING = '待定'
static FULFILLED = '成功'
static REJECTED = '失败'
constructor(func){
this.status = Bromise.PENDING
this.result = null
func(this.resolve.bind(this),this.reject.bind(this))
}
resolve(result){
if(this.status === Bromise.PENDING){
this.status = Bromise.FULFILLED
this.result = result
}
}
reject(result){
if(this.status === Bromise.PENDING){
this.status = Bromise.REJECTED
this.result = result
}
}
then(onFULFILLED,onREJECTED){
if(this.status === Bromise.FULFILLED){
onFULFILLED(this.result)
}
if(this.status === Bromise.REJECTED){
onREJECTED(this.result)
}
}
}
let bromise = new Bromise((resolve,reject)=>{
resolve('成功')
})
bromise.then(
result => {console.log(result)},
error => {console.log(error)}
)
错误处理
问题一:then方法传入的若不是函数,就不能正常运行
问题二:若抛出异常,则不能正确接收
解决:
class Bromise{
static PENDING = '待定'
static FULFILLED = '成功'
static REJECTED = '失败'
constructor(func){
this.status = Bromise.PENDING
this.result = null
try{
func(this.resolve.bind(this),this.reject.bind(this))
}catch(err){
this.reject(error)
}
}
resolve(result){
if(this.status === Bromise.PENDING){
this.status = Bromise.FULFILLED
this.result = result
}
}
reject(result){
if(this.status === Bromise.PENDING){
this.status = Bromise.REJECTED
this.result = result
}
}
then(onFULFILLED,onREJECTED){
onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : ()=>{}
onREJECTED = typeof onREJECTED === 'function' ? onREJECTED : ()=>{}
if(this.status === Bromise.FULFILLED){
onFULFILLED(this.result)
}
if(this.status === Bromise.REJECTED){
onREJECTED(this.result)
}
}
}
let bromise = new Bromise((resolve,reject)=>{
resolve('成功')
})
bromise.then(
result =>{console.log(result)},
error =>{console.log(error)}
)
实现异步
问题:若对resolve或reject进行异步调用,则调用then方法的时候状态处于pending,会导致进不去resolve和reject,所以需要进行异步的实现。
resolveCallbacks和rejectCallbacks的作用:当处于pending状态时,将回调函数添加进去这两个数组,等到下个事件循环的时候执行。
class Bromise {
static PENDING = '待定'
static FULFILLED = '成功'
static REJECTED = '失败'
constructor(func) {
this.status = Bromise.PENDING
this.result = null
this.resolveCallbacks = []
this.rejectCallbacks = []
try {
func(this.resolve.bind(this), this.reject.bind(this))
} catch (err) {
this.reject(error)
}
}
resolve(result) {
setTimeout(() => {
if(this.status === Bromise.PENDING){
this.result = result
this.status = Bromise.FULFILLED
this.resolveCallbacks.forEach(callback => callback(result))
}
})
}
reject(result) {
setTimeout(() => {
if(this.status === Bromise.PENDING){
this.result = result
this.status = Bromise.REJECTED
this.rejectCallbacks.forEach(callback => callback(result))
}
})
}
then(onFULFILLED, onREJECTED) {
onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => { }
onREJECTED = typeof onREJECTED === 'function' ? onREJECTED : () => { }
if(this.status === Bromise.PENDING){
this.resolveCallbacks.push(onFULFILLED)
this.rejectCallbacks.push(onREJECTED)
}
if (this.status === Bromise.FULFILLED) {
setTimeout(() => {
onFULFILLED(this.result)
})
}
if (this.status === Bromise.REJECTED) {
setTimeout(() => {
onREJECTED(this.result)
})
}
}
}
then方法返回Promise(链式调用)
class Bromise {
static PENDING = '待定'
static FULFILLED = '成功'
static REJECTED = '失败'
constructor(func) {
this.status = Bromise.PENDING
this.result = null
this.resolveCallbacks = []
this.rejectCallbacks = []
try {
func(this.resolve.bind(this), this.reject.bind(this))
} catch (err) {
this.reject(error)
}
}
resolve(result) {
setTimeout(() => {
if (this.status === Bromise.PENDING) {
this.result = result
this.status = Bromise.FULFILLED
this.resolveCallbacks.forEach(callback => callback(result))
}
})
}
reject(result) {
setTimeout(() => {
if (this.status === Bromise.PENDING) {
this.result = result
this.status = Bromise.REJECTED
this.rejectCallbacks.forEach(callback => callback(result))
}
})
}
then(onFULFILLED, onREJECTED) {
return new Bromise((resolve, reject) => {
onFULFILLED = typeof onFULFILLED === 'function' ? onFULFILLED : () => { }
onREJECTED = typeof onREJECTED === 'function' ? onREJECTED : () => { }
if (this.status === Bromise.PENDING) {
this.resolveCallbacks.push(onFULFILLED)
this.rejectCallbacks.push(onREJECTED)
}
if (this.status === Bromise.FULFILLED) {
setTimeout(() => {
onFULFILLED(this.result)
})
}
if (this.status === Bromise.REJECTED) {
setTimeout(() => {
onREJECTED(this.result)
})
}
})
}
}
问题
这个实现实际上有很大的问题,Promise.resolve和Promise.reject本来是微任务,但是这里的代码搞成了宏任务。例如,对于下面的代码:
setTimeout(() => {
console.log(3)
})
let promise = new Promise((resolve, reject) => {
resolve(1)
})
promise.then(result => { console.log(result) })
console.log(2)
结果理应是:2 1 3
我的代码的结果:2 3 1
我在网上查阅了很多博客,基本上结果都是1 2 3或者是2 3 1,都和本来的正确结果相去甚远。
可以说:只要代码里面有setTimeout,都不是正确的Promise,Promise自己本来是不应该产生任何宏任务的。
那么如何实现真正的Promise呢?
这就需要后续的深入研究了。