I've lost count of the number of versions I've read of a handwritten promise. But I didn't write one myself. Last night with my colleagues he said it was simple, I asked him to write a scene, good guy to write after the promise how can not be used, but still strong finally write out. Make your own wave while there's still heat
First, to MDN carefully review the use of promise in the end
For the record: Promise doesn’t have the source code; its underlying browser, V8, is already implemented. It’s actually implemented in c++
2. Make promises in your head
class myPromise {
constructor () {
this.status = 'pending'
}
then () {}
catch () {}
finally () {}
all () {}
This is a big pity. /** * allSettled * Until all promises are settled, which is a big pity or rejected. Return a promise that completes after all promises have completed. With an array of objects, each corresponding to the result of each promise. * /
allSettled () { }
any () {}
race () {}
reject () {}
resolve () {}
}
Copy the code
Now that we have the basic structure out, let’s make a new promise and see what it looks like
const p = new Promise((resolve, reject) = >{})console.log(p)
Copy the code
This Promise is a pending state. Only when we invoke ‘resolve’, it will become a pity state, and when we invoke ‘Reject’, it will become ‘Rejected’
— How come this state looks like this… Well, let’s define the constructor based on what it prints
constructor (handle) {
this['[[PromiseState]]'] = 'pending'
this['[[PromiseResult]]'] = undefined
}
Copy the code
Third, parsing the implementation
1. When we new a promis instance, we pass a function to the promise, so we receive a function (Handle) in the promise, which contains a resolve and a reject call, so handle has two parameters
2. According to the printed results, we will change the promiseState and put the result set into the PromiseResult when we resolve or reject
class myPromise {
constructor (handle) {
this['[[PromiseState]]'] = 'pending'
this['[[PromiseResult]]'] = undefined
handle((res) = > {
this['[[PromiseState]]'] = 'fulfilled'
this['[[PromiseResult]]'] = res
}, (err) = > {
this['[[PromiseState]]'] = 'rejected'
this['[[PromiseResult]]'] = err
}) // Execute immediately
}
then () {}
catch () {}
finally () {}
all () {}
This is a big pity. /** * allSettled * Until all promises are settled, which is a big pity or rejected. Return a promise that completes after all promises have completed. With an array of objects, each corresponding to the result of each promise. * /
allSettled () { }
any () {}
race () {}
reject () {}
resolve () {}
}
const myP = new myPromise((resolve, reject) = >{})console.log('myP', myP)
Copy the code
—- Yes
then
Then receives two callback functions, which we are used to writing error messages into a catch
then (successCallback, failCallback) {
if (this['[[PromiseState]]'= = ='fulfilled') {
successCallback && successCallback(this['[[PromiseResult]]'])}else {
failCallback && failCallback(this['[[PromiseResult]]'])}}Copy the code
—- IF I write ‘then’ I can do ‘resolve’, ‘reject’ but if I add ‘setTimeout’ I can do nothing. Writing then this way is an immediate function. So it’s gonna have to be remodeled
4. You can’t execute it immediately, so you can store the callback first and then execute it in resolve or Reject
Note: Only resolve or reject is called before the callback is executed
class myPromise {
constructor (handle) {
this['[[PromiseState]]'] = 'pending'
this['[[PromiseResult]]'] = undefined
this.resolveFn = undefined
this.rejectFn = undefined
handle(this.#resolve.bind(this), this.#reject.bind(this)) //
}
/** * I use resolve and reject as internal functions */ for maintenance purposes
#resolve (val) {
this['[[PromiseState]]'] = 'fulfilled'
this['[[PromiseResult]]'] = val
console.log('this.resolveFn'.this.resolveFn)
this.resolveFn(val)
}
#reject (err) {
this['[[PromiseState]]'] = 'rejected'
this['[[PromiseResult]]'] = err
this.rejectFn(err)
}
then (successCallback, failCallback) {
this.resolveFn = successCallback
this.rejectFn = failCallback
}
}
const myP = new myPromise((resolve, reject) = > {
setTimeout(() = > {
resolve('jdjkkjdd')},1000)
})
myP.then(res= > {
console.log('res', res)
})
console.log('myP', myP)
Copy the code
5. Let’s talk about multiple ‘THEN’ s, not chained ‘THEN’ s
const p = new Promise((resolve, reject) = > {
resolve('resulr')
})
p.then(res= > {
setTimeout(() = > {
console.log('111', res)
}, 1000)},err= > {
console.log(err)
})
p.then(res= > {
console.log('2222',res)
})
console.log(p)
// ...
// Multiple "then" like this
Copy the code
The result is still normal because I added setTimeout to 111, but the promise we wrote will only be executed once, why? This [‘[[PromiseResult]]’] will be overwritten. Therefore, we will store the resolveFn and rejectFn callback functions as arrays
class myPromise {
constructor (handle) {
this['[[PromiseState]]'] = 'pending'
this['[[PromiseResult]]'] = undefined
this.resolveFn = []
this.rejectFn = []
handle(this.#resolve.bind(this), this.#reject.bind(this)) //
}
/** * I use resolve and reject as internal functions */ for maintenance purposes
#resolve (val) {
this['[[PromiseState]]'] = 'fulfilled'
this['[[PromiseResult]]'] = val
// this.resolveFn && this.resolveFn(val)
// Push in from the back and pull out from the top
const run = () = > {
let cb
while (cb = this.resolveFn.shift()) {
cb && cb(val)
}
}
run()
}
#reject (err) {
this['[[PromiseState]]'] = 'rejected'
this['[[PromiseResult]]'] = err
// this.rejectFn && this.rejectFn(err)
// Push in from the back and pull out from the top
const run = () = > {
let cb
while (cb = this.rejectFn.shift()) {
cb && cb(err)
}
}
run()
}
then (successCallback, failCallback) {
this.resolveFn.push(successCallback)
this.rejectFn.push(failCallback)
}
}
const myP = new myPromise((resolve, reject) = > {
setTimeout(() = > {
resolve('jdjkkjdd')},1000)
})
myP.then(res= > {
console.log('res', res)
})
myP.then(res= > {
console.log('2222', res)
})
console.log('myP', myP)
Copy the code
I can’t take a break. Promise is too difficult ,,,, look good remember a key three even oh ~ later will continue to update to complete