-
-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[js] 第176天 请用js实现一个promise的方法 #1335
Labels
js
JavaScript
Comments
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;
})(); |
面试够用版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);
}
});
});
}
}; |
这里有个比较好的源码实现 Promises/A+ 规范 |
// 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)
}
})
}
})
})
} |
插个眼,后续来研究。 |
先发一下自己写的版本,两个要注意的点: 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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
第176天 请用js实现一个promise的方法
The text was updated successfully, but these errors were encountered: