使用了很久promise方法来解决异步编程问题,今天抽空总结一下promise的设计原理,解释的不好,欢迎指点出来。
1.promise只有两种结果:pending=>resolved(成功),pending=>rejected(失败),状态一旦改变,就不能在改变;
2.then 接收成功返回的值
3.catch接收失败放回的值
在没有promise之前,基本上用callback来解决一个方法执行完后在执行,如果有多个就嵌套多个callback,代码就显得非常臃肿,
而.then .catch模式会让代码逻辑变的清晰,看起来同步模式,其实是异步的。
1.创建class 对象模板,在里面constructor(){} 定义初始的变量,也定义then 和catch 的方法
class Promise {
constructor(fn) {
this.status = statusMap.PENDING; // 初始状态
this.value = undefined; // 成功的值
this.reason = undefined; // 失败的值
this.fulfilledCbs = []; // then fulfilled callback
this.rejectedCbs = []; // 失败后运行的脚本
try {
fn((value) => {
resolvePromise(this, value); // 解析
}, (reason) => {
rejectedPromise(this, reason); // 失败的处理
})
} catch (error) {
rejectedPromise(this, error); //失败处理
}
}
then(onFulfilled,onReject){
// .then 成功里面接收回调的值
}
catch(onReject){
// .catch 失败里面接收回调的值
}
}
2.接下来展开then方法里的判断status状态处理
then(onFulfilled, onRejected) {
const promise1 = this;
const promise2 = new Promise(() => { });
onFulfilled = isFunction(onFulfilled) ? onFulfilled : (value) => { return value }; // 设置默认值
onRejected = isFunction(onRejected) ? onRejected : (err) => { throw err };
// 成功
if (promise1.status === statusMap.FULFILLED) {
isFunction(onFulfilled) && setTimeout(() => {
try {
const x = onFulfilled(promise1.value);
resolvePromise(promise2, x); // 决议
} catch (error) {
rejectedPromise(promise2, error);
}
}, 0);
}
// 失败
if (promise1.status === statusMap.REJECTED) {
isFunction(onRejected) && setTimeout(() => {
try {
const x = onRejected(promise1.reason);
resolvePromise(promise2, x); // 决议
} catch (error) {
rejectedPromise(promise2, error);
}
}, 0);
}
// 进行中,向fulfilledCbs和rejectedCbs push函数方法
if (promise1.status === statusMap.PENDING) {
isFunction(onFulfilled) && promise1.fulfilledCbs.push((val) => {
setTimeout(() => {
try {
const x = onFulfilled(val); // 决议
resolvePromise(promise2, x);
} catch (error) {
rejectedPromise(promise2, error);
}
}, 0)
})
isFunction(onRejected) && promise1.rejectedCbs.push((err) => {
setTimeout(() => {
try {
const x = onRejected(err); // 决议
resolvePromise(promise2, x);
} catch (error) {
rejectedPromise(promise2, error);
}
}, 0)
})
}
return promise2;
}
3.catch里就直接调用then就可以
catch(onRejected){
return this.then(undefined,onRejected);
}
4.在then里面有个resolvePromise决议方法,是处理在promise的resove和reject里传递的是值、对象、function、new promise的
// promise 解析
function resolvePromise(promise, x) {
if (promise === x) {
rejectedPromise(promise, new TypeError('cant be the same'))
return;
}
if (isPromise(x)) {
if (x.status === statusMap.FULFILLED) {
fulfilledPromise(promise, x.value);
return;
}
if (x.status === statusMap.REJECTED) {
rejectedPromise(promise, x.reason);
return;
}
if (x.status === statusMap.PENDING) {
x.then(() => {
fulfilledPromise(promise, x.value);
// return;
}, () => {
rejectedPromise(promise, x.reason);
// return;
})
return;
}
return;
}
// 是对象或函数
if ( x !== null && (isObject(x) || isFunction(x))) {
let then;
let called = false; // promise的状态只能pending->fulfilled;pending->rejected;
try {
then = x.then;
} catch (error) {
rejectedPromise(promise, error);
return;
}
if (isFunction(then)) {
try {
then.call(x, (y) => {
if (called) {
return;
}
called = true;
resolvePromise(promise, y);
// fulfilledPromise(promise.y);
}, (r) => {
if (called) {
return;
}
called = true;
rejectedPromise(promise, r);
})
} catch (error) {
if (called) {
return;
}
called = true;
rejectedPromise(promise, error);
}
return;
} else {
if (called) {
return;
}
called = true;
fulfilledPromise(promise, x);
return;
}
} else { // 不是对象或函数
fulfilledPromise(promise, x);
return;
}
}
5.最后贴上全部的代码
const statusMap = {
PENDING: 'pending',
FULFILLED: 'fulfilled',
REJECTED: 'rejected',
}
// 将promise设置为fulfilled状态
function fulfilledPromise(promise, value) {
if (promise.status !== 'pending') {
return;
}
promise.status = statusMap.FULFILLED;
promise.value = value;
runCbs(promise.fulfilledCbs, value)
}
// 将promise设置为rejected状态
function rejectedPromise(promise, reason) {
if (promise.status !== 'pending') {
return;
}
promise.status = statusMap.REJECTED;
promise.reason = reason;
runCbs(promise.rejectedCbs, reason)
}
function isFunction(fn) {
return Object.prototype.toString.call(fn).toLocaleLowerCase() === "[object function]";
}
function isPromise(p) {
return p instanceof Promise;
}
function isObject(o) {
return Object.prototype.toString.call(o).toLocaleLowerCase() === "[object object]";
}
function runCbs(cbs, value) {
cbs.forEach(cb => cb(value));
}
// promise 解析
function resolvePromise(promise, x) {
if (promise === x) {
rejectedPromise(promise, new TypeError('cant be the same'))
return;
}
if (isPromise(x)) {
if (x.status === statusMap.FULFILLED) {
fulfilledPromise(promise, x.value);
return;
}
if (x.status === statusMap.REJECTED) {
rejectedPromise(promise, x.reason);
return;
}
if (x.status === statusMap.PENDING) {
x.then(() => {
fulfilledPromise(promise, x.value);
}, () => {
rejectedPromise(promise, x.reason);
})
return;
}
return;
}
// 是对象或函数
if ( x !== null && (isObject(x) || isFunction(x))) {
let then;
let called = false;
try {
then = x.then;
} catch (error) {
rejectedPromise(promise, error);
return;
}
if (isFunction(then)) {
try {
then.call(x, (y) => {
if (called) {
return;
}
called = true;
resolvePromise(promise, y);
// fulfilledPromise(promise.y);
}, (r) => {
if (called) {
return;
}
called = true;
rejectedPromise(promise, r);
})
} catch (error) {
if (called) {
return;
}
called = true;
rejectedPromise(promise, error);
}
return;
} else {
if (called) {
return;
}
called = true;
fulfilledPromise(promise, x);
return;
}
} else { // 不是对象或函数
fulfilledPromise(promise, x);
return;
}
}
class Promise {
constructor(fn) {
this.status = statusMap.PENDING;
this.value = undefined;
this.reason = undefined;
this.fulfilledCbs = []; // then fulfilled callback
this.rejectedCbs = [];
try {
fn((value) => {
resolvePromise(this, value);
}, (reason) => {
rejectedPromise(this, reason);
})
} catch (error) {
rejectedPromise(this, error);
}
}
then(onFulfilled, onRejected) {
const promise1 = this;
const promise2 = new Promise(() => { });
onFulfilled = isFunction(onFulfilled) ? onFulfilled : (value) => { return value }; // 设置默认值
onRejected = isFunction(onRejected) ? onRejected : (err) => { throw err };
if (promise1.status === statusMap.FULFILLED) {
isFunction(onFulfilled) && setTimeout(() => {
try {
const x = onFulfilled(promise1.value);
resolvePromise(promise2, x); // 决议
} catch (error) {
rejectedPromise(promise2, error);
}
}, 0);
}
if (promise1.status === statusMap.REJECTED) {
isFunction(onRejected) && setTimeout(() => {
try {
const x = onRejected(promise1.reason);
resolvePromise(promise2, x); // 决议
} catch (error) {
rejectedPromise(promise2, error);
}
}, 0);
}
if (promise1.status === statusMap.PENDING) {
isFunction(onFulfilled) && promise1.fulfilledCbs.push((val) => {
setTimeout(() => {
try {
const x = onFulfilled(val); // 决议
resolvePromise(promise2, x);
} catch (error) {
rejectedPromise(promise2, error);
}
}, 0)
})
isFunction(onRejected) && promise1.rejectedCbs.push((err) => {
setTimeout(() => {
try {
const x = onRejected(err); // 决议
resolvePromise(promise2, x);
} catch (error) {
rejectedPromise(promise2, error);
}
}, 0)
})
}
return promise2;
}
catch(onRejected){
return this.then(undefined,onRejected);
}
}