This is the 9th day of my participation in the November Gwen Challenge. See details: The Last Gwen Challenge 2021.
portal
From zero tear Promise, grasp the realization principle of Promise (1) the realization of the basic structure of the Promise from zero tear Promise, grasp the realization principle of Promise (2) the basic version of the Promise realization from zero tear Promise, Master the implementation principle of the Promise (3) callback hell is what from zero rip Promise, master the implementation principle of the Promise (4) then method chain call preliminary implementation from zero rip Promise, Grasp the implementation principle of the Promise (5) then method chain call advanced implementation from zero rip Promise, grasp the implementation principle of the Promise (6) then method callback why is asynchronous microtask from zero rip Promise, Master the implementation principle of Promise (7)then method chain call core method resolvePromise from zero hand tear Promise, master the implementation principle of Promise (8)then method chain call core method resolvePromise again explore
review
After the introduction of the last few articles, we are now nearing the end of our Promise, and our Promsie now looks like this
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const resolvePromise = (promise, x, resolve, reject) = > {
// 1. Determine whether 'x' is a base type or a reference type.
if(x ! = =null && /^(object|function)$/.test(typeof x)){
let then
Then attribute (' x.chen ') on 'x'. Reject 'if an exception is reported
try{
then = x.then
}catch(e){
reject(e)
}
//3. Determine if 'then' is a function. If it is a function, then it is' Promise ', if not 'resolve'
if(typeof then === 'function') {let called = false / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
try{
then.call(x, (y) = > {
if(called) return / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
called = true
resolvePromise(promise, y, resolve, reject)
},(r) = > {
if(called) return/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
reject(r)
})
}catch(e){
if(called) return/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * added a variable here * * * * * * * * * * * * * * * * * * * * * * * * * / / / / / /
reject(e)
}
}else{
resolve(x)
}
}else{
// Base type data directly resolve
resolve(x)
}
}
class Promise{
constructor(executor){
this.state = PENDING
this.value = undefined
this.reason = undefined
/ / store onFulfilled
this.onResolvedCallbacks = []
/ / store onRejected
this.onRejectedCallbacks = []
const resolve = (value) = > {
if (this.state === PENDING) {
this.value = value
this.state = FULFILLED
// The promise instance will call ondepressing after its state changes
this.onResolvedCallbacks.forEach(fn= > fn())
}
}
const reject = (reason) = > {
if (this.state === PENDING) {
this.reason = reason
this.state = REJECTED
// onRejected called after the promise instance state changes
this.onRejectedCallbacks.forEach(fn= > fn())
}
}
try {
// An error in the execution of the executor function will cause the Promise to fail
executor(resolve,reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected){
let promise = new Promise((resolve, reject) = > {
switch(this.state){
case FULFILLED:
setTimeout(() = > {
try{
let x = onFulfilled(this.value)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
break
case REJECTED:
setTimeout(() = > {
try{
let x = onRejected(this.reason)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
break
default:
this.onResolvedCallbacks.push(() = > {
setTimeout(() = > {
try{
let x = onFulfilled(this.value)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
})
this.onRejectedCallbacks.push(() = > {
setTimeout(() = > {
try{
let x = onRejected(this.reason)
resolvePromise(promise, x, resolve, reject)
} catch(e){
reject(e)
}
})
})
}
})
return promise
}
}
Copy the code
The resolvePromise method resolves minor flaws
- Let’s look at the following code, and say,
then
Return from the callback functionPromise
isthen
Returned by the function itselfPromsie
, there will be problems. - What could go wrong?
- Following the execution logic of our code, first of all
then
The callback function returns onePromsie
, byresolvePromsie
Method to parse. - Take the following code
pThen
Is the firstthen
The return value of the function, and thepThen
As thethen
The return value of the successful callback, thenresolvePromsie
Method is called againpThen
thethen
Methods,pThen
This instance is its ownresolve
withreject
“, thus creating an endless cycle of waiting for their own state. (Like a ridiculous example, I wait for me to cook for myself, we will never wait)
- Following the execution logic of our code, first of all
let p = new Promise((resolve,reject) = > {
resolve('success')})let pThen = then(value= > {
return pThen
}).then(value= > {
console.log('value',value);
},reason= > {
console.log('reason',reason);
})
Copy the code
- So for this problem, we need to reinvent it
resolvePromsie
Method, make a small judgment, the code is as follows
const resolvePromise = (promise, x, resolve, reject) = > {
/ / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * to determine whether x and promsie the same promise, Prevent an infinite loop *********************//////*********
if(x === promise) throw new TypeError('Chaining cycle detected for promise #<Promise>')
// 1. Determine whether 'x' is a base type or a reference type.
if(x ! = =null && /^(object|function)$/.test(typeof x)){
let then
Then attribute (' x.chen ') on 'x'. Reject 'if an exception is reported
try{
then = x.then
}catch(e){
reject(e)
}
//3. Determine if 'then' is a function. If it is a function, then it is' Promise ', if not 'resolve'
if(typeof then === 'function') {let called = false
try{
then.call(x, (y) = > {
if(called) return
called = true
resolvePromise(promise, y, resolve, reject)
},(r) = > {
if(called) return
reject(r)
})
}catch(e){
if(called) return
reject(e)
}
}else{
resolve(x)
}
}else{
// Base type data directly resolve
resolve(x)
}
}
Copy the code
portal
From zero tear Promise, grasp the realization principle of Promise (1) the realization of the basic structure of the Promise from zero tear Promise, grasp the realization principle of Promise (2) the basic version of the Promise realization from zero tear Promise, Master the implementation principle of the Promise (3) callback hell is what from zero rip Promise, master the implementation principle of the Promise (4) then method chain call preliminary implementation from zero rip Promise, Grasp the implementation principle of the Promise (5) then method chain call advanced implementation from zero rip Promise, grasp the implementation principle of the Promise (6) then method callback why is asynchronous microtask from zero rip Promise, Master the implementation principle of Promise (7)then method chain call core method resolvePromise from zero hand tear Promise, master the implementation principle of Promise (8)then method chain call core method resolvePromise again explore