Promise implementation principle
We’ve used promises countless times in our coding, so how do promises come true?
Today we are going to implement a better promise step by step.
I believe that some students already know the principle, so you can review the old and learn the new, we can study together.
1 Implementation of basic promises
A promise has three states: Pending Resolved Rejected. The promise can be switched from the Pending state to Resolved and Rejected only once, and then the final state will remain.
Let’s look at a basic promise in action.
new Promise(function(resolve,reject){
resolve(123)
// reject(456)
}).then(function(data){
console.log('success',data) // success 123
},function(reason){
console.log('fail',reason)
})
Copy the code
Call the method that passes in a Promise an executor, which executes immediately when a Promise is constructed. The parameters of the then method are passed in. The first ondepressing function is the parameter of Promise resolve, which will be executed after the Promise state is resolved; The second onRejected function takes the parameter of Promise Reject and is executed after the Promise state is Rejected.
Parameters like 123 or 456 become the final value of a promise.
From this we implement a basic 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)
}
}
Copy the code
Executor contains asynchronous functions
Then is a pending state
new Promise(function(resolve,reject){
setTimeout(function(){
resolve(123)
},0)
}).then(function(data){
console.log('success',data)
},function(reason){
console.log('fail',reason)
})
Copy the code
The executor function throws error
try{
executor(resolve,reject)
}catch(e){
reject(e)
}
Copy the code
4 Register multiple THEN
Callbacks are placed in arrays
functionPromise (executor){// omit this.resolveCallback = [] this.rejectCallback = [] // omitfunction 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'The self. The value = "reason self. RejectCallback. ForEach (fn = > {fn (reason)}) / / omit}}}Copy the code
5 Chain call
Do not return the same promise
const promise1 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(123)
},0)
})
const promise2 = promise1.then(function (data){
return456},function(reason){
console.log('reason',reason)
})
console.log('compare',promise1 == promise2) // false
Copy the code
So instead of returning the current this, the then function returns a new promise
promise1.then(function(data){
console.log('success',data)
return456},function(reason){
console.log('fail',reason)
}).then(function(data){
console.log('success1',data)
},function(reason){
console.log('fail1',reason)
})
Copy the code
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)
})
Copy the code
6 Returns a promise when a chained call is made
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)
})
Copy the code
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 loop reference')}if(x instanceof Promise){
try{
x.then(function(data){
resolve(data)
},function(reason){
reject(reason)
})
}catch(e){
reject(e)
}
}else{
resolve(x)
}
}
Copy the code
7 through
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
})
Copy the code
The solution
Promise.prototype.then = function(this is a big pity, onFulfilled){// omitted onFulfilled === typeof onFulfilled === this is a big pityfunction ? onFulfilled : function(data){return data}
onRejected = typeof onRejected === function ? onRejected : function(data){returnData} // omit}Copy the code
8 Asynchronous Execution
Refer to the Promise A+ specification:
conclusion
Promise to realize the core is then processed, other methods promise. All, promise. Race, promise. Reject, promise. Resolve, promise. After then clear catch would be easy to write.
The source address
discuss
How might our Promise implementation be different from the Promise implementation built into the browser?
The resources
Juejin. Cn/post / 684490… www.ituring.com.cn/article/665… Stackoverflow.com/questions/5…