在我们写代码的过程中用过了无数次promise,那么promise是如何实现的呢?
今天我们来一步步实现一个较为完善的promise。
相信有一部分同学已经知道了原理,那么可以温故知新,大家再一起学习下。
promise有3个状态:pending resolved rejected,并且只能单向地从pending状态向resolved和rejected状态转换,且状态只能转换一次,之后保持最终态。
我们看一个基本的promise的用法。
new Promise(function(resolve,reject){
resolve(123)
// reject(456)
}).then(function(data){
console.log('success',data) // success 123
},function(reason){
console.log('fail',reason)
})
把传入Promise的方法称为executor,executor在promise构造时立即执行。 传入then方法的参数,第一个onFulfilled函数,参数为Promise resolve时的参数,在promise状态为resolved后执行;第二个onRejected函数,参数为Promise reject时的参数,在promise状态为rejected后执行;
123或456这样的参数成为promise的终值。
由此我们实现一个基本的promise
function Promise (executor){
const self = this
this.state = 'pending'
this.value = undefined
this.resolveCallback = undefined
this.rejectCallback = undefined
function resolve(data){
if(self.state === 'pending'){
self.state = 'resolved'
self.value = data
if(self.resolveCallback){
self.resolveCallback(data)
}
}
}
function reject (reason){
if(self.state === 'pending'){
self.state = 'rejected'
self.value = reason
if(self.rejectCallback){
self.rejectCallback(reason)
}
}
}
executor(resolve,reject)
}
Promise.prototype.then = function (onFulfilled,onRejected){
if(this.state === 'pending'){
this.resolveCallback = onFulfilled
this.rejectCallback = onRejected
}
if(this.state === 'resolved'){
onFulfilled(this.value)
}
if(this.state === 'rejected'){
onRejected(this.value)
}
}
走到then时是pending状态
new Promise(function(resolve,reject){
setTimeout(function(){
resolve(123)
},0)
}).then(function(data){
console.log('success',data)
},function(reason){
console.log('fail',reason)
})
try{
executor(resolve,reject)
}catch(e){
reject(e)
}
回调放在数组中
function Promise (executor){
// 省略
this.resolveCallback = []
this.rejectCallback = []
// 省略
function resolve(data){
if(self.state === 'pending'){
self.state = 'resolved'
self.value = data
self.resolveCallback.forEach(fn => {
fn(data)
})
}
}
function reject (reason){
if(self.state === 'pending'){
self.state = 'rejected'
self.value = reason
self.rejectCallback.forEach(fn => {
fn(reason)
})
}
}
// 省略
}
不返回同一个promise
const promise1 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(123)
},0)
})
const promise2 = promise1.then(function (data){
return 456
},function(reason){
console.log('reason',reason)
})
console.log('compare',promise1 == promise2) // false
因此then函数不返回当前的this,而返回新的promise
promise1.then(function(data){
console.log('success',data)
return 456
},function(reason){
console.log('fail',reason)
}).then(function(data){
console.log('success1',data)
},function(reason){
console.log('fail1',reason)
})
Promise.prototype.then = function (onFulfilled,onRejected){
var self = this
if(this.state === 'pending'){
return new Promise(function(resolve,reject){
self.resolveCallback.push(function(){
var x = onFulfilled(self.value)
resolve(x)
})
self.rejectCallback.push(function(){
var x = onRejected(self.value)
reject(x)
})
})
}
if(this.state === 'resolved'){
return new Promise(function(resolve,reject){
var x = onFulfilled(self.value)
resolve(x)
})
}
if(this.state === 'rejected'){
return new Promise(function(resolve,reject){
var x = onRejected(self.value)
reject(x)
})
}
}
const promise1 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(123)
},0)
})
const promise1 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(123)
},0)
})
promise1.then(function(data){
console.log('success',data)
return new Promise(function(resolve,reject){
resolve(456)
})
},function(reason){
console.log('fail',reason)
}).then(function(data){
console.log('success1',data)
},function(reason){
console.log('fail1',reason)
})
Promise.prototype.then = function (onFulfilled,onRejected){
var self = this
var promise2
if(this.state === 'pending'){
promise2 = new Promise(function(resolve,reject){
self.resolveCallback.push(function(){
try{
var x = onFulfilled(self.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
self.rejectCallback.push(function(){
try{
var x = onRejected(self.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
})
}
if(this.state === 'resolved'){
promise2 = new Promise(function(resolve,reject){
try{
var x = onFulfilled(self.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
}
if(this.state === 'rejected'){
promise2 = new Promise(function(resolve,reject){
try{
var x = onRejected(self.value)
resolvePromise(promise2,x,resolve,reject)
}catch(e){
reject(e)
}
})
}
return promise2
}
function resolvePromise(promise,x,resolve,reject){
if(promise === x){
throw new Error('promise循环引用')
}
if(x instanceof Promise){
try{
x.then(function(data){
resolve(data)
},function(reason){
reject(reason)
})
}catch(e){
reject(e)
}
}else{
resolve(x)
}
}
const promise1 = new Promise(function(resolve,reject){
setTimeout(function(){
// resolve(123)
reject(123)
},0)
})
promise1.then().then()
.then(function(data){
console.log('success1',data)
},function(reason){
console.log('fail1',reason) // fail1 123
})
解决方案
Promise.prototype.then = function (onFulfilled,onRejected){
// 省略
onFulfilled = typeof onFulfilled === function ? onFulfilled : function(data){return data}
onRejected = typeof onRejected === function ? onRejected : function(data){return data}
// 省略
}
参考promise A+规范规范: then函数回调应当异步执行。因此需要把then函数返回的promise的executor用异步函数包围来实现异步。
promise实现的核心是then的处理,其他的方法 promise.all,promise.race,promise.reject, promise.resolve , promise.catch在then明确后就容易写了。
我们实现的Promise和浏览器内置的promise的实现可能有什么不同?
https://juejin.im/post/5ab466a35188257b1c7523d2
https://www.ituring.com.cn/article/66566
https://stackoverflow.com/questions/59503772/is-the-javascript-es6-promise-exactly-the-same-as-promise-a