This is the 7th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 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 hand tear Promise, grasp the implementation principle of the Promise (6) then method callback why is asynchronous microtask
review
After a few introductions, our Promise now looks like this
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
const resolvePromise = (promise, x, resolve, reject) = >{}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
then
MethodresolvePromise
methods
-
The purpose of resolvePromise is to parse the return value of the then callback function to determine what state the THEN method should return.
-
- In the first place to judge
x
Base type data, or reference type, base type data directlyresolve
That is ok.
- In the first place to judge
-
- If it is referential data, try to fetch it
x
On thethen
Properties (x.then
) if an exception is reported while getting the attributereject
- If it is referential data, try to fetch it
-
- judge
then
Is it a function or not? If it’s a function then we say it’s a functionPromise
If not, thenresolve
- judge
-
- if
x
Is aPromise
, and we call histhen
Method, and then inthen
Method to callresolve
orreject
If the call returns an errorreject
- if
-
- This shows if the callback in the then function returns
Promise
Then the state of the return value of the then function is the same as that returned by the callbackPromise
States are closely related.
- This shows if the callback in the then function returns
/* promise => then promise x => then promise x => then promise x => then Reject */ of the promise that the then function returns
const resolvePromise = (promise, x, resolve, reject) = > {
/ / 1.
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') {// 4. If 'x' is a 'Promise', we call his' then 'method, then in the' then 'callback, we call' resolve 'or' reject ', and if the call returns an error, 'reject'
try{
then.call(x, (y) = > {
resolvePromise(promise, y, resolve, reject)
},(r) = > {
reject(r)
})
}catch(e){
reject(e)
}
}else{
resolve(x)
}
}else{
// Base type data directly resolve
resolve(x)
}
}
Copy the code
- 6. Repeat recursive call for serial number 1 in the following picture
resolvePromise
To prevent, for example, the following code from returning a multiple nested resultPromise
In turn, you need to recurse.
let p = new Promise((resolve,reject) = > {
resolve('success')
})
p.then(value= > {
console.log('value',value);
// The then successful callback returns a Promise, and its value is a Promise, nested multiple times.
// So the recursive call to resolvePromise resolves this situation
return new Promise((resolve,reject) = > { // The first promise
resolve(
// The second promise
new Promise((resolve,reject) = > {
resolve('success')}))})},reason= > {
console.log('reason',reason);
}).then(value= > {
console.log('value',value);
},reason= > {
console.log('reason',reason);
})
Copy the code
- The execution result
Print the result twice, correct. (Print the first time for P.teng and the second time for p.teng. Then)
So here’s ourPromise
That long
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') {//4. If 'x' is a 'Promise', we call his' then 'method, then in the' then 'callback, we call' resolve 'or' reject ', and if the call returns an error, 'reject'
try{
then.call(x, (y) = > {
resolvePromise(promise, y, resolve, reject)
},(r) = > {
reject(r)
})
}catch(e){
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
}
}
module.exports=Promise
Copy the code
At this point, ourthen
Method, there are some minor flaws, soon our Promise will be completed, the next article will continue to finish
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 hand tear Promise, grasp the implementation principle of the Promise (6) then method callback why is asynchronous microtask