Git Product home page Git Product logo

Comments (6)

4noth1ng avatar 4noth1ng commented on August 15, 2024 1
class MyPromise {
  static PENDING = "pending";
  static FULFILLED = "fulfilled";
  static REJECTED = "rejected";
  constructor(executor) {
    this.status = MyPromise.PENDING;
    this.value = null;
    this.callbacks = [];
    executor(this.resolve.bind(this), this.reject.bind(this));
  }
  resolve(value) {
    this.status = MyPromise.FULFILLED;
    this.value = value;
    setTimeout(() => {
      this.callbacks.forEach((cb) => {
        cb.onFulfilled(this.value);
      });
    });
  }
  reject(value) {
    this.status = MyPromise.REJECTED;
    this.value = value;
    setTimeout(() => {
      this.callbacks.forEach((cb) => {
        cb.onRejected(this.value);
      });
    });
  }
  then(onFulfilled, onRejected) {
    if (typeof onFulfilled !== "function") onFulfilled = (value) => value;
    if (typeof onRejected !== "function") onRejected = (value) => value;
    return new MyPromise((resolve, reject) => {
      if (this.status === MyPromise.PENDING) {
        this.callbacks.push({
          onFulfilled: (value) => {
            const res = onFulfilled(value);
            this.resolvePromise(res, resolve, reject);
          },
          onRejected: (value) => {
            const res = onFulfilled(value);
            this.resolvePromise(res, resolve, reject);
          },
        });
      }
      if (this.status === MyPromise.FULFILLED) {
        setTimeout(() => {
          const res = onFulfilled(this.value);
          this.resolvePromise(res, resolve, reject);
        });
      }
      if (this.status === MyPromise.REJECTED) {
        setTimeout(() => {
          const res = onFulfilled(this.value);
          this.resolvePromise(res, resolve, reject);
        });
      }
    });
  }

  resolvePromise(res, resolve, reject) {
    try {
      // const res = onFulfilled(value);
      if (res instanceof MyPromise) {
        res.then(resolve, reject);
      } else {
        resolve(res);
      }
    } catch (error) {
      reject(error);
    }
  }
}

from js-challenges.

huihuilang53 avatar huihuilang53 commented on August 15, 2024

class myPromise {
constructor(executor) {//传入的函数(resolve,reject)=>{}
this.state = myPromise.PENDING
this.value = null
this.reason = null
this.onFulfilledFns = [] //异步回调队列
this.onRejectedFns = []
const resolve = value => {
if (this.state === myPromise.PENDING) {//只有在pendding才可修改状态
this.state = myPromise.FULFILLED
this.value = value
//执行异步回调
this.onFulfilledFns.forEach(fn => typeof fn === 'function' && fn())
}
}
const reject = reason => {
if (this.state === myPromise.PENDING) {//只有在pendding才可修改状态
this.state = myPromise.REJECTED
this.reason = reason

    this.onRejectedFns.forEach(fn => fn())
  }
}
executor(resolve, reject) //执行传入new promise的函数,执行resolve或reject

}
then(onFulfilled, onRejected) {//接收成功、失败的回调函数,或接收值, 值会透传
//处理值穿透
if (typeof onFulfilled !== 'function') onFulfilled = a => a
if (typeof onRejected !== 'function') {
onRejected = e => {
throw e
}
}
return new myPromise((resolve, reject) => {//返回new promise实例,链式调用
//执行微任务同步回调
if (this.state === myPromise.FULFILLED) {
// 封装execute
queueMicrotask(() => {
execute(onFulfilled, this.value, resolve, reject)//执行回调函数,将函数中的return用resolve包裹
})
} else if (this.state === myPromise.REJECTED) {
// 封装execute
queueMicrotask(() => execute(onRejected, this.reason, resolve, reject))
}
//执行异步回调,添加进数组,resolve时再调用函数
else {
this.onFulfilledFns.push(() =>
queueMicrotask(() =>
// 封装execute
execute(onFulfilled, this.value, resolve, reject)
)
)
this.onRejectedFns.push(() =>
queueMicrotask(() =>
// 封装execute
execute(onRejected, this.reason, resolve, reject)
)
)
}
})
}
}
function execute(cb, value, resolve, reject) {
try {
// 判断onFulfilled,onRejected返回值是否是Promise对象
const res = cb(value)
if (res instanceof myPromise) {
//如果是,那么新的Promise对象的状态就等于原来的Promise对象的状态
res.then(resolve, reject)
} else {
// 否则就是成功的状态
resolve(res)
}
} catch (e) {
reject(e)
}
}
myPromise.PENDING = 'pending'
myPromise.FULFILLED = 'fulfilled'
myPromise.REJECTED = 'rejected'

from js-challenges.

liuruil avatar liuruil commented on August 15, 2024

Promise A+规范要求obj是一个对象或函数,这样写是否是更合理一点
address: https://promisesaplus.com/#point-53

function isPromise(obj) {
  return !!(obj && (typeof obj === "object" || typeof obj === 'function') && typeof obj.then === "function");
}

from js-challenges.

Erica-WX avatar Erica-WX commented on August 15, 2024

请问这两边都需要执行队列中的函数吗?有点没太明白

then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      this._pushHandler(onFulfilled, FULFILLED, resolve, reject);
      this._pushHandler(onRejected, REJECTED, resolve, reject);
      this._runHandlers(); // 执行队列
    });
  }

_changeState(newState, value) {
    if (this._state !== PENDING) {
      // 目前状态已经更改
      return;
    }
    this._state = newState;
    this._value = value;
    this._runHandlers(); // 状态变化,执行队列
  }

from js-challenges.

PI-TY avatar PI-TY commented on August 15, 2024

if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
// 如果 x 为对象或函数
try {
// 把 x.then 赋值给 then
var then = x.then;
} catch (e) {
// 如果取 x.then 的值时抛出错误 e ,则拒绝 promise
return reject(e);
}

    /**
     * 如果 then 是函数,将 x 作为函数的作用域 this 调用之。
     * 传递两个回调函数作为参数,
     * 第一个参数叫做 `resolvePromise` ,第二个参数叫做 `rejectPromise`
     */
    if (typeof then === 'function') {
        // 如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
        let called = false; // 避免多次调用
        try {
            then.call(
                x,
                // 如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
                y => {
                    if (called) return;
                    called = true;
                    resolvePromise(promise2, y, resolve, reject);
                },
                // 如果 rejectPromise 以据因 r 为参数被调用,拒绝 promise
                r => {
                    if (called) return;
                    called = true;
                    reject(r);
                }
            )
        } catch (e) {
            /**
             *  如果调用 then 方法抛出了异常 e
             * 如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
             */
            if (called) return;
            called = true;
            // 拒绝 promise
            reject(e);
        }
    } else {
        如果 then 不是函数,以 x 为参数执行 promise
        resolve(x);
    }

from js-challenges.

YMnotafraid avatar YMnotafraid commented on August 15, 2024
function Promise(executor) {
  this.state = "pending";
  this.value = undefined;
  this.reason = undefined;
  // 保存成功回调
  this.onResolvedCallbacks = [];
  // 保存失败回调
  this.onRejectedCallbacks = [];

  let _this = this;
  try {
    executor(resolve, reject);
  } catch (error) {
    reject(error);
  }

  function resolve(value) {
    if (_this.state === "pending") {
      _this.state = "resolved";
      _this.value = value;
      _this.onResolvedCallbacks.forEach((cb) => cb(value));
    }
  }
  function reject(reason) {
    if (_this.state === "pending") {
      _this.state = "rejected";
      _this.reason = reason;
      _this.onRejectedCallbacks.forEach((cb) => cb(reason));
    }
  }
}

Promise.prototype.then = function (onFulfilled, onRejected) {
  onFulfilled =
    typeof onFulfilled === "function" ? onFulfilled : (value) => value;
  onRejected =
    typeof onRejected === "function"
      ? onRejected
      : (err) => {
          throw err;
        };

  let promise2 = new Promise((resolve, reject) => {
    // 等待态判断,此时异步代码还未走完,回调入数组队列
    if (this.state === "pending") {
      this.onResolvedCallbacks.push(() => {
        queueMicrotask(() => {
          try {
            let x = onFulfilled(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      });

      this.onRejectedCallbacks.push(() => {
        queueMicrotask(() => {
          try {
            let x = onRejected(this.value);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      });
    }
    if (this.state === "resolved") {
      queueMicrotask(() => {
        try {
          let x = onFulfilled(this.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    }
    if (this.state === "rejected") {
      queueMicrotask(() => {
        try {
          let x = onRejected(this.reason);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      });
    }
  });
  return promise2;
};

function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    reject(new TypeError("请避免Promise循环引用"));
  }
  let called;
  if (x !== null && (typeof x === "object" || typeof x === "function")) {
    // 可能是个对象或是函数
    try {
      let then = x.then;
      if (typeof then === "function") {
        then.call(
          x,
          (y) => {
            if (called) return;
            called = true;
            // 递归调用,传入y若是Promise对象,继续循环
            resolvePromise(promise2, y, resolve, reject);
          },
          (r) => {
            if (called) return;
            called = true;
            reject(r);
          }
        );
      } else {
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    // 普通值结束递归
    resolve(x);
  }
}

from js-challenges.

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.