Skip to content

Instantly share code, notes, and snippets.

@SirM2z
Created June 5, 2019 10:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SirM2z/130a4e6281e0f602047e934c538490b5 to your computer and use it in GitHub Desktop.
Save SirM2z/130a4e6281e0f602047e934c538490b5 to your computer and use it in GitHub Desktop.
const PENDING = "pending";
const RESOLVED = "resolved"; // fulfilled
const REJECTED = "rejected"; //rejected
class Promise {
// 构造函数接受一个执行器作为参数
constructor(executor) {
// promise 状态
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
// 成功回调数组
this.onFulfilledCallbacks = [];
// 失败回调数组
this.onRejectedCallbacks = [];
const resolve = value => {
// 实现异步执行 then 方法中的两个参数 onFulfilled onRejected
// 对应第4条要求
const timer = setTimeout(() => {
if (this.status === PENDING) {
clearTimeout(timer);
this.value = value;
this.status = RESOLVED;
this.onFulfilledCallbacks.forEach(func => {
func(this.value);
});
}
}, 0);
};
const reject = reason => {
// 实现异步执行 then 方法中的两个参数 onFulfilled onRejected
// 对应第4条要求
const timer = setTimeout(() => {
if (this.status === PENDING) {
clearTimeout(timer);
this.reason = reason;
this.status = REJECTED;
this.onRejectedCallbacks.forEach(func => {
func(this.reason);
});
}
}, 0);
};
try {
// 执行 执行器,并传入两个方法作为参数
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
// then 方法接受两个方法作为参数
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
// onFulfilled 不是 function 时设置默认方法
if (typeof onFulfilled !== "function") {
onFulfilled = res => res;
}
this.onFulfilledCallbacks.push(() => {
try {
const res = onFulfilled(this.value);
if (res instanceof Promise) {
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (error) {
reject(error);
}
});
// onRejected 不是 function 时设置默认方法
if (typeof onRejected !== "function") {
onRejected = err => {
throw new Error(err instanceof Error ? err.message : err);
};
}
this.onRejectedCallbacks.push(() => {
try {
const res = onRejected(this.reason);
if (res instanceof Promise) {
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (error) {
reject(error);
}
});
})
}
catch(onRejected) {
return this.then(null, onRejected);
}
static all(promiseAry = []) {
return new Promise((resolve, reject) => {
let finishNum = 0;
let result = [];
const len = promiseAry.length;
for (let i = 0; i < len; i++) {
promiseAry[i].then(val => {
finishNum++;
result[i] = val;
if (finishNum === len) {
resolve(result);
}
}, reject)
}
})
}
static resolve(arg) {
return new Promise(function(resolve){
resolve(arg);
});
}
static reject(arg) {
return new Promise(function(resolve, reject){
reject(arg);
});
}
}
module.exports = Promise;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment