“This is the 16th day of my participation in the November Gwen Challenge. See details of the event: The Last Gwen Challenge 2021”.
portal
Tear Promise from zero hand, master the realization of the Promise principle (1) of the basic structure of the Promise
From scratch tear Promise, grasp the Promise realization principle (2) of the basic version of the Promise
Tear Promise from scratch, Master Promise realization principle (3) Callback what is hell
From scratch tear Promise, master the Promise realization principle (4) then method chain call preliminary implementation
From scratch tear Promise, master the Promise realization principle (5) then method chain call of the advanced implementation
Why is the callback of then method asynchronous microtask
(7) Then the core method of chain call resolvePromise
(8) The core method of chain call of then method resolvePromise is explored again
(9) Then method chain call core method resolvePromise complete
Tear Promise from scratch, master the realization principle of Promise (10)then method to complete all
Test whether all promises comply with PromiseA+ by learning how to implement promises (11)
What? Promise.resolve() can also return a failed Promise (12)
review
After the introduction of the last article, we completed the Promise, catch, Reject, and resolve methods, and now Promsie looks like this.
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
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 / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 we find that value is a Promise, we need to call value's then method to recursively resolve it
if(value instanceof Promise) {return value.then(resolve,reject); // recursive parsing
}
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){
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v= > v
onRejected = typeof onRejected === 'function' ? onRejected : err= > { throw err }
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
}
catch(onRejected){
return this.then(null, onRejected)
}
static rsolve(value){
return new Promise((resolve,reject) = >{ resolve(value); })}static reject(reason){
return new Promise((resolve,reject) = >{ reject(reason); }}})Copy the code
This article introduces
- What this article mainly accomplishes is,
finally
Method, this method is often asked in the interview, is how to achieve.finally
The method is the prototypical method.
Hand to tearfinally
methods
-
The finally method accepts a callback that is executed whether the Promise succeeds or fails.
-
Finally methods are implemented internally through then methods and promise.resolve.
-
Principle is as follows
finally(cb){
return this.then(
(y) = > {
return Promise.resolve(cb()).then(() = > y)
},
(r) = > {
return Promise.resolve(cb()).then(() = > {throw r})
}
)
}
Copy the code
parsingfinally
Realize the principle of
- I believe that you and I saw the above implementation, feel the brain buzzing, the heart of ten thousand grass mud horse pentium, write what shit.
- Here I will answer your doubts through four small examples, because
finally
The implementation of theresolve
In order to facilitate my expression, I marked some serial numbers in the following two pictures for you to compare according to my ideas.
Key code for finally implementation
Key code for the Resolve implementation
-
The sequence numbers used to explain the execution logic of resolve are those identified in the above two images. If you are not familiar with the resolve implementation process, you can read the previous article through the portal, which specifically describes the implementation of Resolve.
-
Case 1
Promise.resolve('ok').finally(() = > { return new Promise((resolve,reject) = >{ setTimeout(() = > { resolve('inner ok')},1000); }) }).then((data) = > { console.log('success', data) }, (err) = > { console.log('failure', err) }) Copy the code
-
Native Promise execution results (browser console print)
-
Run the example based on the code we implemented, in the following order.
Promise.resolve(‘ OK ‘) –> call finally to execute F1 where y is OK –> execute R1 –>F3 The Promsie value that finally returns success is inner OK –> execute promise.resolve in R2 F1 Returns a Promise of success –> execute F5
At this point, F5 returns y(OK), that is, finally returns a successful Promise of OK –> then executes a successful callback, and prints’ successful OK ‘.
-
-
Example 2
Promise.resolve('ok').finally(() = > { return new Promise((resolve,reject) = >{ setTimeout(() = > { reject('inner ok')},1000); }) }).then((data) = > { console.log('success', data) }, (err) = > { console.log('failure', err) }) Copy the code
-
Native Promise execution results (browser console print)
-
Run the example based on the code we implemented, in the following order.
Promise.resolve(‘ OK ‘) –> call finally to execute F1 where y is OK –> execute R1 –>F3 finally returns the Promsie that failed because inner OK –> execute R3 F1 Resolve returns a failed Promise because inner OK –> then does not execute F5. Then replaces the second failed callback by default, so F1 returns a failed Promsie because inner OK, Inner OK –> call then to execute the failed callback and print ‘failed inner OK’
-
-
I’m not going to take you through case 3 and case 4. You can analyze it the way I do, provided you’ve written promises yourself, otherwise it will be hard to analyze. If you don’t know promises very well, you can read my series of articles and implement a Promise from scratch.
portal
Tear Promise from zero hand, master the realization of the Promise principle (1) of the basic structure of the Promise
From scratch tear Promise, grasp the Promise realization principle (2) of the basic version of the Promise
Tear Promise from scratch, Master Promise realization principle (3) Callback what is hell
From scratch tear Promise, master the Promise realization principle (4) then method chain call preliminary implementation
From scratch tear Promise, master the Promise realization principle (5) then method chain call of the advanced implementation
Why is the callback of then method asynchronous microtask
(7) Then the core method of chain call resolvePromise
(8) The core method of chain call of then method resolvePromise is explored again
(9) Then method chain call core method resolvePromise complete
Tear Promise from scratch, master the realization principle of Promise (10)then method to complete all
Test whether all promises comply with PromiseA+ by learning how to implement promises (11)
What? Promise.resolve() can also return a failed Promise (12)