Comments (6)
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.
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.
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.
请问这两边都需要执行队列中的函数吗?有点没太明白
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.
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.
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)
- 代理模式 HOT 1
- 装饰器模式 HOT 1
- 手写new关键字 HOT 1
- 实现有序数组生成平衡二叉搜索树,ACM模式(2023美团暑期实习一面手撕)
- 版本号排序(2023美团暑期实习一面) HOT 2
- 将html字符串转为树状结构
- 对象去重 HOT 2
- 【开源自荐】推荐一个每日更新的前端面试题库
- bind
- 我的解决方案
- 【开源自荐】SolidUI 一句话生成任何图形
- 百度2023秋招:把数组排成最小的数 HOT 5
- 实现简易版的useState HOT 1
- 手写Instanceof详细 HOT 1
- 现在有一大段Markdown文本,解析Markdown文本。并且能够根据这段文本自动生成目录,点击目录可以跳转到Markdown文本对应的位置。类似语雀的目录树。
- 求更新 HOT 1
- 下拉菜单过渡
- 全排列
- 数组乱序(时间复杂度O(n)) HOT 1
- 排序找第几个最大
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from js-challenges.