前言
最後一篇,說說除了then之外的
Resolve和Reject
實現了前面的then後,這兩個方法就很簡答了。
static resolve(value) {
return new Eswang((resolve, reject) => {
if (value instanceof Eswang) {
value.then(resolve, reject);
} else resolve(value);
});
}
這裏處理resolve中的Promise的方式和前面一樣。
Reject也類似:
static reject(value) {
return new Eswang((resolve, reject) => {
reject(value);
});
}
All
先貼代碼:
static all(promises) {
const values = [];
return new Eswang((resolve, reject) => {
promises.forEach(promise => {
promise.then(
value => {
values.push(value);
if (values.length === promises.length) resolve(values);
},
reason => {
reject(reason);
}
);
});
});
}
這裏爲了判斷所有的promise都成功,使用了數組長度和傳入的Promises長度的比較。
同時只要有一個失敗,reject就會執行。
race
因爲狀態改變不能覆蓋的特性,所以race實現起來相當簡單:
static race(promises) {
return new Eswang((resolve, reject) => {
promises.map(promise => {
promise.then(
value => {
resolve(value);
},
reason => {
reject(reason);
}
);
});
});
}
最後
貼一下全家福:
class Eswang {
static PENDING = "pending";
static FUFILLED = "fufillied";
static REJECTED = "rejected";
constructor(executor) {
this.status = Eswang.PENDING;
this.val = null;
this.callbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.status === Eswang.PENDING) {
this.status = Eswang.FUFILLED;
this.val = value;
setTimeout(() => {
this.callbacks.map(callback => {
callback.onFufilled(this.val);
});
});
}
}
reject(reason) {
if (this.status === Eswang.PENDING) {
this.status = Eswang.REJECTED;
this.val = reason;
setTimeout(() => {
this.callbacks.map(callback => {
callback.onReject(this.val);
});
});
}
}
then(onFufilled, onReject) {
if (typeof onFufilled !== "function") {
onFufilled = () => this.val;
}
if (typeof onReject !== "function") {
onReject = () => this.val;
}
let promise = new Eswang((resolve, reject) => {
if (this.status === Eswang.PENDING) {
this.callbacks.push({
onFufilled: val => {
this.parse(promise, onFufilled(val), resolve, reject);
},
onReject: val => {
this.parse(promise, onReject(val), resolve, reject);
}
});
}
if (this.status === Eswang.FUFILLED) {
setTimeout(() => {
this.parse(promise, onFufilled(this.val), resolve, reject);
});
}
if (this.status === Eswang.REJECTED) {
setTimeout(() => {
this.parse(promise, onReject(this.val), resolve, reject);
});
}
});
return promise;
}
parse(promise, result, resolve, reject) {
if (promise == result) {
throw new Error("cuole");
}
try {
if (result instanceof Eswang) {
result.then(resolve, reject);
} else resolve(result);
} catch (error) {
reject(error);
}
}
static resolve(value) {
return new Eswang((resolve, reject) => {
if (value instanceof Eswang) {
value.then(resolve, reject);
} else resolve(value);
});
}
static reject(value) {
return new Eswang((resolve, reject) => {
reject(value);
});
}
static all(promises) {
const values = [];
return new Eswang((resolve, reject) => {
promises.forEach(promise => {
promise.then(
value => {
values.push(value);
if (values.length === promises.length) resolve(values);
},
reason => {
reject(reason);
}
);
});
});
}
static race(promises) {
return new Eswang((resolve, reject) => {
promises.map(promise => {
promise.then(
value => {
resolve(value);
},
reason => {
reject(reason);
}
);
});
});
}
}