Coder Social home page Coder Social logo

Comments (1)

Cosen95 avatar Cosen95 commented on May 26, 2024

具体实现讲解可参考这里

const PENDING = "PENDING";
const RESOLVED = "RESOLVED";
const REJECTED = "REJECTED";

const resolvePromise = (promise2, x, resolve, reject) => {
  console.log(promise2);
  if (promise2 === x) {
    // # 2.3.1 If promise and x refer to the same object, reject promise with a TypeError as the reason.
    return reject(
      new TypeError("Chaining cycle detected for promise #<Promise>")
    );
  }

  if ((typeof x === "object" && x !== null) || typeof x === "function") {
    // 防止多次调用成功和失败
    // # 2.3.3.3.3 If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.
    let called;
    try {
      // 取x的then属性,如果是一个函数,认定其为promise
      let then = x.then;
      if (typeof then === "function") {
        // # 2.3.3.3 If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise
        then.call(
          x,
          (y) => {
            // # 2.3.3.3.1 If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).
            // 采用promise的成功结果将值向下传递
            // 这里的y有可能还是一个promise,所以递归调用resolvePromise
            if (called) {
              return;
            }
            called = true;
            resolvePromise(promise2, y, resolve, reject);
          },
          (r) => {
            // # 2.3.3.3.2 If/when rejectPromise is called with a reason r, reject promise with r
            // 采用失败结果向下传递
            if (called) {
              return;
            }
            called = true;
            reject(r);
          }
        );
      } else {
        // 说明x是一个普通对象
        resolve(x);
      }
    } catch (e) {
      if (called) {
        return;
      }
      called = true;
      reject(e);
    }
  } else {
    // x是一个普通值
    // # 2.3.4 If x is not an object or function, fulfill promise with x
    resolve(x);
  }
};

class Promise {
  constructor(executor) {
    this.status = "PENDING"; // 默认pending状态
    this.value = undefined;
    this.reason = undefined;
    this.onResolvedCallbacks = [];
    this.onRejectedCallbacks = [];
    let resolve = (value) => {
      if (this.status === PENDING) {
        this.value = value;
        this.status = RESOLVED;
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };

    let reject = (reason) => {
      if (this.status === PENDING) {
        this.reason = reason;
        this.status = REJECTED;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };

    try {
      executor(resolve, reject); // 默认执行器会立即执行
    } catch (error) {
      reject(e);
    }
  }
  then(onfulfilled, onrejected) {
    // onfulfilled onrejected是可选参数
    // # 2.2.1 Both onFulfilled and onRejected are optional arguments:
    onfulfilled =
      typeof onfulfilled === "function" ? onfulfilled : (data) => data;
    onrejected =
      typeof onrejected === "function"
        ? onrejected
        : (err) => {
            throw err;
          };
    let promise2 = new Promise((resolve, reject) => {
      if (this.status === RESOLVED) {
        setTimeout(() => {
          try {
            // # 2.2.2 If onFulfilled is a function:
            //    # 2.2.2.1 it must be called after promise is fulfilled, with promise’s value as its first argument.
            let x = onfulfilled(this.value);
            // x可能是普通值 也可能是promise
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            // # 2.2.3 If onRejected is a function,
            //    # 2.2.3.1 it must be called after promise is rejected, with promise’s reason as its first argument.
            let x = onrejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }

      if (this.status === PENDING) {
        this.onResolvedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onfulfilled(this.value);
              // x可能是普通值 也可能是promise
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onrejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
      }
    });
    return promise2;
  }
}

// resolve方法
Promise.resolve = function (val) {
  return new Promise((resolve, reject) => {
    resolve(val);
  });
};

// reject方法
Promise.reject = function (val) {
  return new Promise((resolve, reject) => {
    reject(val);
  });
};

// race方法
Promise.race = function (promises) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(resolve, reject);
    }
  });
};

// all方法(获取所有的promise,都执行then,把结果放到数组,一起返回)

Promise.defer = Promise.deferred = function () {
  let dfd = {};
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
};

module.exports = Promise;

from fe_interview.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.