[js] 第176天 请用js实现一个promise的方法
haizhilin2013 opened this issue · 6 comments
haizhilin2013 commented
第176天 请用js实现一个promise的方法
encountermm commented
const PromisePolyfill = (() => {
//状态管理
const promiseStatusSymbol = Symbol('PromiseStatus');
const promiseValueSymbol = Symbol('PromiseValue');
const STATUS = {
PENDING: 'PENDING',
FULFILLED: 'FULFILLED',
REJECTED: 'REJECTED'
};
//resolve操作设置值和状态
function resolve() {
this[promiseValueSymbol] = arguments[0];
this[promiseStatusSymbol] = STATUS['FULFILLED'];
}
//reject操作设置值和状态
function reject() {
this[promiseValueSymbol] = arguments[0];
this[promiseStatusSymbol] = STATUS['REJECTED'];
}
class myPromise {
constructor(resolver) {
if (typeof resolver !== 'function') {
throw new TypeError(`parameter 1 must be a function, but get a ${typeof func}`);
}
this[promiseStatusSymbol] = STATUS['PENDING'];//初始状态为pending
resolver(
resolve.bind(this),//绑定promise实例对象
reject.bind(this)
);
}
then(callback) {
//开一个定时器监听状态变化,如果有变化则执行callback
const interval = setInterval(() => {
if (this[promiseStatusSymbol] === 'FULFILLED' || this[promiseStatusSymbol] === 'REJECTED') {
clearInterval(interval);
callback(this[promiseValueSymbol], resolve.bind(this), reject.bind(this));
this[promiseStatusSymbol] = 'PENDING';//执行完后把状态改回,方便下一个then方法进行定时轮询
}
});
return this;
}
}
return myPromise;
})();
vkboo commented
面试够用版
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(function(resolve,reject){resolve(1)});
p.then(function(x){console.log(x)})
//输出1
大厂专供版
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
function Promise(excutor) {
let that = this; // 缓存当前promise实例对象
that.status = PENDING; // 初始状态
that.value = undefined; // fulfilled状态时 返回的信息
that.reason = undefined; // rejected状态时 拒绝的原因
that.onFulfilledCallbacks = []; // 存储fulfilled状态对应的onFulfilled函数
that.onRejectedCallbacks = []; // 存储rejected状态对应的onRejected函数
function resolve(value) { // value成功态时接收的终值
if(value instanceof Promise) {
return value.then(resolve, reject);
}
// 实践中要确保 onFulfilled 和 onRejected 方法异步执行,且应该在 then 方法被调用的那一轮事件循环之后的新执行栈中执行。
setTimeout(() => {
// 调用resolve 回调对应onFulfilled函数
if (that.status === PENDING) {
// 只能由pending状态 => fulfilled状态 (避免调用多次resolve reject)
that.status = FULFILLED;
that.value = value;
that.onFulfilledCallbacks.forEach(cb => cb(that.value));
}
});
}
function reject(reason) { // reason失败态时接收的拒因
setTimeout(() => {
// 调用reject 回调对应onRejected函数
if (that.status === PENDING) {
// 只能由pending状态 => rejected状态 (避免调用多次resolve reject)
that.status = REJECTED;
that.reason = reason;
that.onRejectedCallbacks.forEach(cb => cb(that.reason));
}
});
}
// 捕获在excutor执行器中抛出的异常
// new Promise((resolve, reject) => {
// throw new Error('error in excutor')
// })
try {
excutor(resolve, reject);
} catch (e) {
reject(e);
}
}
Promise.prototype.then = function(onFulfilled, onRejected) {
const that = this;
let newPromise;
// 处理参数默认值 保证参数后续能够继续执行
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : value => value;
onRejected =
typeof onRejected === "function" ? onRejected : reason => {
throw reason;
};
if (that.status === FULFILLED) { // 成功态
return newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try{
let x = onFulfilled(that.value);
resolvePromise(newPromise, x, resolve, reject); // 新的promise resolve 上一个onFulfilled的返回值
} catch(e) {
reject(e); // 捕获前面onFulfilled中抛出的异常 then(onFulfilled, onRejected);
}
});
})
}
if (that.status === REJECTED) { // 失败态
return newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(that.reason);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
});
}
if (that.status === PENDING) { // 等待态
// 当异步调用resolve/rejected时 将onFulfilled/onRejected收集暂存到集合中
return newPromise = new Promise((resolve, reject) => {
that.onFulfilledCallbacks.push((value) => {
try {
let x = onFulfilled(value);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
that.onRejectedCallbacks.push((reason) => {
try {
let x = onRejected(reason);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
});
}
};
abinnq commented
// promise 三个状态
var PENDING = 'pending';
var RESOLVED = 'resolved';
var REJECTED = 'rejected';
/**
*
* @param {function} executor
*/
function PromiseA (executor) {
// 保存一下this, 防止this出现指向不明
var _this = this;
// 初始化 promise 的值
_this.data = undefined;
// 初始化 promise 的状态
_this.status = PENDING;
// 保存成功和失败的回调函数
_this.resolvedCallbacks = [];
_this.rejectedCallbacks = [];
// 调用成功函数
function resolve(value) {
// 在pending时修改对应状态, 和 promise 值
setTimeout(function() {
if(_this.status === PENDING) {
_this.status = RESOLVED;
_this.data = value;
_this.resolvedCallbacks.forEach(function(fn) {
fn();
});
}
})
}
// 调用失败函数
function reject(reason) {
// 在pending时修改对应状态, 和 promise 值
setTimeout(function() {
if(_this.status === PENDING) {
_this.status = REJECTED;
_this.data = reason;
_this.rejectedCallbacks.forEach(function(fn) {
fn();
});
}
})
}
// 用于处理 new PromiseA((resolve, reject) => {throw new Error('error')})
try {
executor(resolve, reject);
} catch (reason) {
reject(reason)
}
}
/**
*
* @param {promise} promise2 then 执行后返回 新的Promise对象
* @param {*} x promise中onResolved 的返回值
* @param {*} resolve promise2的resolve方法
* @param {*} reject promise2的reject方法
*/
function resolvePromise(promise2, x, resolve, reject) {
var then;
// 为了避免多次调用
var called = false;
if(promise2 === x) {
return reject(new TypeError('循环回调'));
}
// x 如果是普通值(非 object 或 function), 直接resolve
if(x !== null && (typeof x === 'object' || typeof x === 'function')){
// 每个promise 都会有then方法, 使用_then保存, 防止出错, 使用try catch
try {
then = x.then;
if(typeof then === 'function') {
// 确定 this 指向x
then.call(x, function(y) {
if(called) return;
called = true;
return resolvePromise(promise2, y, resolve, reject);
}, function(e) {
if(called) return;
called = true;
return reject(e);
})
} else {
resolve(x);
}
} catch (err) {
if(called) return;
called = true;
reject(err);
}
} else {
resolve(x);
}
}
/**
* @param {function} onResolved 成功回调
* @param {function} onRejected 失败回调
*/
PromiseA.prototype.then = function(onResolved, onRejected) {
var _this = this;
var promise2;
// 值的穿透
onResolved = typeof onResolved === 'function' ? onResolved : function(value) {return value};
onRejected = typeof onRejected === 'function' ? onRejected : function(reason) {throw reason};
return promise2 = new PromiseA(function(resolve, reject) {
// 异步执行, 保证调用顺序
setTimeout(function() {
// 状态是成功状态, 立即执行成功回调, 并传入其值
if(_this.status === RESOLVED) {
// 针对内部
try {
var x = onResolved(_this.data);
resolvePromise(promise2, x, resolve, reject);
} catch(reason) {
reject(reason);
}
}
// 状态是失败状态, 立即执行失败回调, 并传入其值
if(_this.status === REJECTED) {
try {
var x = onRejected(_this.data);
resolvePromise(promise2, x, resolve, reject);
} catch (reason) {
reject(reason);
}
}
// 状态是等待, 将回调函数保存起来
if(_this.status === PENDING) {
_this.resolvedCallbacks.push(function() {
try {
var x = onResolved(_this.data);
resolvePromise(promise2, x, resolve, reject);
} catch (reason) {
reject(reason);
}
})
_this.rejectedCallbacks.push(function() {
try {
var x = onRejected(_this.data);
resolvePromise(promise2, x, resolve, reject);
} catch (reason) {
reject(reason)
}
})
}
})
})
}
fireairforce commented
插个眼,后续来研究。
wind8866 commented
先发一下自己写的版本,两个要注意的点:
1、构造函数的回调函数是修改状态
2、then、catch、finally参数执行时要判断是否是pending状态,如果是,先加入队列下来等待状态改变再执行
class PromiseFake {
#status = 'Pending'
#result = undefined
#thenList = []
#catchList = []
#finilyList = []
constructor(callback) {
callback((result) => {
this.#status = 'Fulfilled'
this.#result = result
this.#delay()
}, (result) => {
this.#status = 'Rejected'
this.#result = result
this.#delay()
})
}
#delay() {
if (this.#status === 'Fulfilled') {
this.#thenList.forEach((thenCallback) => {
thenCallback(this.#result)
})
} else {
this.#catchList.forEach((errorCallback) => {
errorCallback(this.#result)
})
}
this.#finilyList.forEach((callback) => {
callback()
})
this.#catchList = []
this.#thenList = []
this.#finilyList = []
}
then(callback) {
if (this.#status === 'Pending') {
this.#thenList.push(callback)
} else if (this.#status === 'Fulfilled') {
callback(this.#result)
}
return this
}
catch(callback) {
if (this.#status === 'Pending') {
this.#catchList.push(callback)
} else if (this.#status === 'Rejected') {
callback(this.#result)
}
return this
}
finally(callback) {
if (this.#status === 'Pending') {
this.#finilyList.push(callback)
} else {
callback(this.#result)
}
return this
}
}
const p2 = new PromiseFake((resolve, reject) => {
setTimeout(() => resolve(33), 1000)
})
p2
.then((result) => { console.log(result, 1) })
.catch(e => { console.log(e) })
.finally(() => { console.log('finish') })
p2.then((result) => { console.log(result, 2) })
setTimeout(() => {
p2.then((result) => { console.log(result, 3) })
}, 5000)