Recently, I saw many articles about Promise source code parsing, or implementing a Promise by myself, and I suddenly wanted to make a wheel for myself to try.
First of all, the wheel does not fully comply with any standards and norms, but is written on the understanding and feelings of the regular Promise after use. It is purely entertainment.
The following is the implementation code:
// Object Type Judgment const is = (typeAsString) => obj => Object.prototype.toString.call(obj) === typeAsString // Determine whether it is an Error object const isError = is('[object Error]') /** * Customize Promise objects * @param {(resolve: (value: any) => void, reject: (reason: any) => void) => void} executor */ function MyPromise(executor) { this.executor = executor // The initial state is pending... this.status = 'pending' /** * Internal decision state, only in pending state can continue to execute * @param {number} value */ function resolve(value) { if (this.status === 'pending') { // Ensure that only once is executed this.onfulfilled = ___onfulfilled.call(this, value) } } /** * To cache the execution results of the resolve method * @param {*} value value It's the result of the resolve method's execution. */ function ___onfulfilled(value) { this.status = 'fulfilled' // Change internal status /** * @param {(value: number) => void} onfulfilled Here are the parameters passed in the then method */ return (onfulfilled) => { return onfulfilled(value) // } } /** * The Method of Triggering Anomalies * @param {string} reason */ function reject(reason) { if (this.status === 'pending') { // Ensure that only once is executed this.onrejected = ___onrejected.call(this, reason) } } /** * * @param {Error} reason If the incoming object is not an Error object, it will be wrapped in Error */ function ___onrejected(reason) { this.status = 'rejected' // Change internal status return (onrejected) => { reason = isError(reason) ? reason : new Error(reason) return onrejected(reason) } } /** * @param {(value: number) => any} onfulfilled Processing Successful Functions * @param {(reason: any) => void} onrejected Handling functions with exceptions, if this parameter is passed in, the catch method will not catch it. */ this.then = function(onfulfilled, onrejected) { const self = this return new MyPromise((resolve, reject) => { setTimeout(function waitStatus() { switch (self.status){ case 'fulfilled': // resolved if (onfulfilled) { // Give the return value of the onfulfilled method to resolve to ensure that the next. then method can get the return value of the previous. then method const nextValue = self.onfulfilled(onfulfilled) resolve(nextValue) } else { resolve() // No incoming parameters, pretend to be incoming parameters:) } break case 'rejected': // rejected if (!onrejected) { // If the onrejected parameter is not passed, a default implementation is implemented to ensure that the catch method can capture it onrejected = (reason) => reason } const nextReject = self.onrejected(onrejected) reject(nextReject) break case 'pending': // default: setTimeout(waitStatus, 0) // As long as it's pending, wait until it's not pending break } }, 0); }) } /** * Catching exceptions * @param {(reason: any) => void} onrejected */ this.catch = function(onrejected) { const self = this setTimeout(function reject() { if (self.status === 'rejected') { self.onrejected(onrejected) } else { setTimeout(reject, 0); } }, 0); } // Direct execution this.executor(resolve.bind(this), reject.bind(this)); }
At present, without considering the correctness of parameter input, assuming that all the parameters are correct, it can run normally in nodejs environment. The following is the test code:
// Override the default Proise object in the nodejs environment global.Promise = MyPromise async function test () { const r = await new Promise((resolve) => { setTimeout(() => { resolve(121) }, 1000); }) console.log(r) // Print 121 } test()
The above code mainly uses the setTimeout method to check the internal state of Promise object, and make corresponding processing as soon as changes occur. The source code is here This is the case. Welcome to pat bricks.
Thanks for watching!