大家好,我是右子。
大家是不是在面试的时候有被要求手写一个promise?我们来看一下如何自定义一个promise。
一般这种题,可以用倒推的形式进行,我们来看一下promise是如何书写的。
let status = "";
let p1 = new Promise((resolve,reject)=>{
if(status==="ok"){
resolve("success");
}else if(status==="errno"){
resolve("errno");
}else{
reject();
}
});
p1.then(resp=>{
console.log(resp);
});
由此我们来封装一下简版
class MyPromise{
constructor(fn){
this.status = "pending"; // fulfilled、rejected、pending
this.resolved = null;
this.rejected = null;
fn && fn(this.resolve.bind(this),this.reject.bind(this))
}
then(cb){
cb && cb(this.resolved);
}
catch(cb){
cb && cb(this.rejected);
}
resolve(resp){
this.resolved = resp;
this.status = "fulfilled";
}
reject(resp){
this.rejected = resp;
this.status = "rejected";
}
}
let status = "";
let mp1 = new MyPromise((resolve,reject)=>{
if(status==="ok"){
resolve("success");
}else if(status==="errno"){
resolve("errno");
}else{
reject("异常");
}
});
mp1.then(resp=>{
console.log("ok callback");
})
实现一个 Promise
function MyPromise(executor) {
let self = this
self.status = 'pending'
self.data = undefined
self.onResolvedCallback = []
self.onRejectedCallback = []
function resolve(value) {
if (self.status === 'pending') {
self.status = 'resolved'
self.data = value
for (let i = 0; i < self.onResolvedCallback.length; i++) {
self.onResolvedCallback[i](value)
}
}
}
function reject(reason) {
if (self.status === 'pending') {
self.status = 'rejected'
self.data = reason
for (let i = 0; i < self.onRejectedCallback.length; i++) {
self.onRejectedCallback[i](reason)
}
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
MyPromise.prototype.then = function (onResolved, onRejected) {
let self = this
let promise2
onResolved = typeof onResolved === 'function' ? onResolved : function (v) { return v }
onRejected = typeof onRejected === 'function' ? onRejected : function (r) { throw r }
if (self.status === 'resolved') {
return promise2 = new MyPromise(function (resolve, reject) {
try {
let x = onResolved(self.data)
if (x instanceof MyPromise) {
x.then(resolve, reject)
}
resolve(x)
} catch (error) {
reject(error)
}
})
}
if (self.status === 'rejected') {
return promise2 = new MyPromise(function (resolve, reject) {
try {
let x = onRejected(self.data)
if (x instanceof MyPromise) {
x.then(resolve, reject)
}
} catch (error) {
reject(error)
}
})
}
if (self.status === 'pending') {
return promise2 = new MyPromise(function (resolve, reject) {
self.onResolvedCallback.push(function (value) {
try {
let x = onResolved(self.data)
if (x instanceof MyPromise) {
x.then(resolve, reject)
}
} catch (error) {
reject(error)
}
})
self.onRejectedCallback.push(function (reason) {
try {
let x = onRejected(self.data)
if (x instanceof MyPromise) {
x.then(resolve, reject)
}
} catch (error) {
reject(error)
}
})
})
}
}
MyPromise.prototype.catch = function (onRejected) {
return this.then(null, onRejected)
}