当前位置:网站首页>Realization principle of promise (1)

Realization principle of promise (1)

2020-12-07 11:05:39 Master of Wannian Da Ye Yi

        //  Three states 
        const PENDING = "pending";
        const RESOLVED = "resolved";
        const REJECTED = "rejected";
        // promise  Receive a function parameter , The function is executed immediately 
        function MyPromise(fn) {
            let _this = this;
            _this.currentState = PENDING;
            _this.value = undefined;
            //  Used to hold  then  Callback in , Only when  promise
            //  Status as  pending  Will be cached , And each instance can cache at most one 
            _this.resolvedCallbacks = [];
            _this.rejectedCallbacks = [];
            _this.resolve = function (value) {
                if (value instanceof MyPromise) {
                    //  If  value  It's a  Promise, Recursive execution 
                    return value.then(_this.resolve, _this.reject);
                }
                setTimeout(() => {
                    //  Asynchronous execution , The order of execution must be guaranteed 
                    if (_this.currentState === PENDING) {
                        _this.currentState = RESOLVED;
                        _this.value = value;
                        _this.resolvedCallbacks.forEach((cb) => cb());
                    }
                });
            };
            _this.reject = function (reason) {
                setTimeout(() => {
                    //  Asynchronous execution , Ensure the order of execution 
                    if (_this.currentState === PENDING) {
                        _this.currentState = REJECTED;
                        _this.value = reason;
                        _this.rejectedCallbacks.forEach((cb) => cb());
                    }
                });
            };
            //  Used to solve the following problems 
            // new Promise(() => throw Error('error))
            try {
                fn(_this.resolve, _this.reject);
            } catch (e) {
                _this.reject(e);
            }
        }
        MyPromise.prototype.then = function (onResolved, onRejected) {
            var self = this;
            //  standard  2.2.7,then  Must return a new  promise
            var promise2;
            //  standard  2.2.onResolved  and  onRejected  Are optional parameters 
            //  If the type is not a function, you need to ignore , At the same time, it also realizes the transmission through 
            // Promise.resolve(v).then().then((value) => console.log(value))
            onResolved =
                typeof onResolved === "function" ? onResolved : (v) => v;
            onRejected = typeof onRejected === "function" ? onRejected : (r) => {throw r};
            if (self.currentState === RESOLVED) {
                return (promise2 = new MyPromise(function (resolve, reject) {
                    //  standard  2.2.4, Guarantee  onFulfilled,onRjected  Asynchronous execution 
                    //  So use the  setTimeout  Under the parcel 
                    setTimeout(function () {
                        try {
                            var x = onResolved(self.value);
                            resolutionProcedure(promise2, x, resolve, reject);
                        } catch (reason) {
                            reject(reason);
                        }
                    });
                }));
            }
            if (self.currentState === REJECTED) {
                return (promise2 = new MyPromise(function (resolve, reject) {
                    setTimeout(function () {
                        //  Asynchronous execution onRejected
                        try {
                            var x = onRejected(self.value);
                            resolutionProcedure(promise2, x, resolve, reject);
                        } catch (reason) {
                            reject(reason);
                        }
                    });
                }));
            }
            if (self.currentState === PENDING) {
                return (promise2 = new MyPromise(function (resolve, reject) {
                    self.resolvedCallbacks.push(function () {
                        //  Considering that there may be an error , So use  try/catch  The parcel 
                        try {
                            var x = onResolved(self.value);
                            resolutionProcedure(promise2, x, resolve, reject);
                        } catch (r) {
                            reject(r);
                        }
                    });
                    self.rejectedCallbacks.push(function () {
                        try {
                            var x = onRejected(self.value);
                            resolutionProcedure(promise2, x, resolve, reject);
                        } catch (r) {
                            reject(r);
                        }
                    });
                }));
            }
        };
        //  standard  2.3
        function resolutionProcedure(promise2, x, resolve, reject) {
            //  standard  2.3.1,x  Unable to join  promise2  identical , Avoid circular references 
            if (promise2 === x) {
                return reject(new TypeError("Error"));
            }
            //  standard  2.3.2
            //  If  x  by  Promise, Status as  pending  Need to wait or execute 
            if (x instanceof MyPromise) {
                if (x.currentState === PENDING) {
                    x.then(function (value) {
                        //  The function is called again to confirm that  x resolve  Of 
                        //  What kind of parameter is , If it's a basic type, again  resolve
                        //  Pass the value to the next  then
                        resolutionProcedure(promise2, value, resolve, reject);
                    }, reject);
                } else {
                    x.then(resolve, reject);
                }
                return;
            }
            //  standard  2.3.3.3.3
            // reject  perhaps  resolve  If one of them has been executed , Ignore the others 
            let called = false;
            //  standard  2.3.3, Judge  x  Whether it's an object or a function 
            if (x !== null && (typeof x === "object" || typeof x === "function")) {
                //  standard  2.3.3.2, If you can't take it out  then, Just  reject
                try {
                    //  standard  2.3.3.1
                    let then = x.then;
                    //  If  then  Is the function , call  x.then
                    if (typeof then === "function") {
                        //  standard  2.3.3.3
                        then.call(
                            x,
                            (y) => {
                                if (called) return;
                                called = true;
                                //  standard  2.3.3.3.1
                                resolutionProcedure(promise2, y, resolve, reject);
                            },
                            (e) => {
                                if (called) return;
                                called = true;
                                reject(e);
                            }
                        );
                    } else {
                        //  standard  2.3.3.4
                        resolve(x);
                    }
                } catch (e) {
                    if (called) return;
                    called = true;
                    reject(e);
                }
            } else {
                //  standard  2.3.4,x  For the basic type 
                resolve(x);
            }
        }

版权声明
本文为[Master of Wannian Da Ye Yi]所创,转载请带上原文链接,感谢
https://chowdera.com/2020/12/20201207110410397r.html