ES5/ES6 实现基本 Promise

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ES5-Promise</title>
  </head>
  <body>
    <script>
      // ES5 写法
      function myPromise(constructor) {
        let self = this;
        self.status = "pending"; // 定义状态改变前的初始状态

        self.value = undefined; // 定义状态为resolved的时候的状态
        self.reason = undefined; // 定义状态为rejected的时候的状态

        function resolve(value) {
          // 两个==="pending",保证了了状态的改变是不不可逆的
          if (self.status === "pending") {
            self.value = value;
            self.status = "resolved";
          }
        }

        function reject(reason) {
          // 两个==="pending",保证了了状态的改变是不不可逆的
          if (self.status === "pending") {
            self.reason = reason;
            self.status = "rejected";
          }
        }

        // 捕获构造异常
        try {
          constructor(resolve, reject);
        } catch (e) {
          reject(e);
        }
      }

      myPromise.prototype.then = function (onFullfilled, onRejected) {
        let self = this;
        switch (self.status) {
          case "resolved":
            onFullfilled(self.value);
            break;
          case "rejected":
            onRejected(self.reason);
            break;
          default:
        }
      };

      //  测试实例
      var p = new myPromise((resolve, reject) => {
        resolve("success");
      });

      p.then((x) => {
        console.log(1);
        console.log(x);
      });
      p.then((x) => {
        console.log(2);
        console.log(x);
      });

      p.then((x) => {
        console.log(3);
        console.log(x);
      });
    </script>
  </body>
</html>

ES6-Promise

const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';

function resolvePromise(promise2, x, resolve, reject) {
    if (x === promise2) {
        throw Error('不能返回自身');
    }
    if (x instanceof _Promise) {
        if (x.status === PENDING) {
            x.then(
                y => resolvePromise(promise2, y, resolve, reject),
                reject
            )
        } else if (x.status === FULLFILLED) {
            resolve(x.value);
        } else {
            reject(x.value);
        }
    } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        let then = null;
        try {
            then = x.then;
        } catch (error) {
            reject(error);
        }
        if (typeof then === 'function') {
            let called = false;
            try {
                then.call(
                    x,
                    res => {
                        if (called) {
                            return;
                        }
                        called = true;
                        resolvePromise(promise2, res, resolve, reject);
                    },
                    error => {
                        if (called) {
                            return;
                        }
                        called = true;
                        reject(error);
                    }
                )
            } catch (error) {
                if (called) {
                    return;
                }
                called = true;
                reject(error);
            }
        } else {
            resolve(x);
        }
    } else {
        resolve(x);
    }
}

class _Promise {
    constructor(executor) {
        this.status = PENDING;
        this.value = null;
        this.fullfilledCallbacks = [];
        this.rejectedCallbacks = [];

        try {
            executor(this.resolve.bind(this), this.reject.bind(this));
        } catch (error) {
            this.reject(error);
        }
    }
    resolve(value) {
        if (this.status === PENDING) {
            setTimeout(() => {
                this.status = FULLFILLED;
                this.value = value;
                this.fullfilledCallbacks.forEach(callback => callback(value));
            })
        }
    }

    reject(reason) {
        if (this.status === PENDING) {
            setTimeout(() => {
                this.status = REJECTED;
                this.value = reason;
                this.rejectedCallbacks.forEach(callback => callback(reason));
            })

        }
    }

    then(onFullfilled, onRejected) {
        onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }

        let promise2 = new _Promise((resolve, reject) => {
            if (this.status === PENDING) {
                this.fullfilledCallbacks.push(() => {
                    try {
                        let x = onFullfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
                this.rejectedCallbacks.push(() => {
                    try {
                        let x = onRejected(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            }

            if (this.status === FULLFILLED) {
                setTimeout(() => {
                    try {
                        let x = onFullfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            }

            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            }
        });
        return promise2;
    }
}

猜你喜欢

转载自blog.csdn.net/zq18877149886/article/details/132408196