Promise基本实现
promise state状态的描述
A promise must be in one of three states: pending, fulfilled, or rejected.
1),When pending, a promise:may transition to either the fulfilled or rejected state.
2),When fulfilled, a promise:must not transition to any other state. must have a value, which must not change.
3),When rejected, a promise:must not transition to any other state.must have a reason, which must not change.
代码实现
const PENDING = 'pending';
const REJECTED = 'rejected';
const FULFILLED = 'fulfilled';
class Promise{
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
const resolve = (value) => {
if (this.status === FULFILLED) return;
this.value = value;
this.status = FULFILLED;
}
const reject = (reason) => {
if (this.status === REJECTED) return;
this.reason = reason;
this.status = REJECTED;
}
try {
executor(resolve, reject);
} catch (e) {
reject(e)
}
}
}
promise then method
描述
then(onFulfilled, onRejected) {
const promise2 = new Promise1((resolve, reject)=>{
});
return promise2
}
- A promise’s then method accepts two arguments:
promise.then(onFulfilled, onRejected)
- then中的回调函数的返回值,决定了下一个then的行为:因此要特殊处理
- then中的参数为函数,then中回调函数的返回值,会传递个下一个then的回调函数中的形参。此时分两种情况
1,被then中失败函数捕获
上一个返回的是失败态的Promise或者抛出异常,会被下一个一个then中的失败所捕获
2,被then中成功函数捕获;// Promise失败状态 Promise.reject('1').then((v)=>{ console.log(v); //不走这里 }, (r)=>{ console.log(r); // 1 }) // 抛出异常错误 Promise.resolve('1').then(()=>{ return throw new Error('error') }).then(()=>{ }, (r)=>{ console.log(r); //会捕获到上一个then中抛出的错误 })
上一个返回的成功的promise或者说上一个的失败回调返回的是一个普通的值,会被下一个then的成功所捕获这里的普通值指的是非promise, 非错误,非异常
Promise.reject('1').then(()=>{ }, (r)=>{ return 'pre then error' }).then((v)=>{ console.log(v); //pre then error捕获上一个then失败函数中返回的普通值 })
- then中的参数为非函数,
因为then没有传递值或者说值不是函数,因此值向下传递,也就是常说的值的穿透问题
// 以下是原生Promise的行为 Promise.resolve('1').then().then().then((res)=>{ console.log(res); //1, })
- then中回调函数非返回值为Promise
// then中返回成功的promise Promise.resolve('1').then(v=>{ return new Promise((resolve,reject)=>{ resolve('ok') }) }).then((v)=>{ console.log(v); //ok }); //then中返回promise失败态 Promise.resolve('1').then(v=>{ return new Promise((resolve,reject)=>{ reject('reject') }) }).then((v)=>{ console.log(v, 'onFulfilled'); //不走这里 },(r)=>{ console.log(r, 'onRejected');//reject onRejected })
- then中的参数为函数,then中回调函数的返回值,会传递个下一个then的回调函数中的形参。此时分两种情况
then 方法的完整实现
then(onFulfilled, onRejected) {
const promise2 = new Promise1((resolve, reject) => {
// 处理参数为非函数的情况
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
// If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected with the same reason.
onRejected = typeof onRejected === 'function' ? onRejected : r => reject(r);
// 以下处理Promise状态异步改变的情况
// 需要then的回调函数暂存起来
// 需要对then函数的回调函数的返回值做处理 ,因为返回值有可能是Promise
// onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].
// 因此这里需要异步来处理
if (this.status === PENDING) {
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
//
if (this.status === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
// const x = onRejected(this.reason); // 要求必须要在同意栈中调用
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
});
return promise2;
}
platform code的意思
Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.
The Promise Resolution Procedure
resolvePromise 方法的实现
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
return reject(new TypeError('不能循环引用'));
}
// x为对象或者函数
if ((x !== null && typeof x === 'object') || typeof x === 'function') {
let called = false; //加开关防止then中的状态被篡改
try {
// x为函数
let then = x.then;
if (typeof then === 'function') {
then.call(x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject); //继续递归处理y
},
(r) => {
if (called) return;
called = true;
reject(r)
},
)
//x为对象
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
// x为普通值
}else {
resolve(x);
}
}
Promise基本代码的实现
const PENDING = 'pending';
const REJECTED = 'rejected';
const FULFILLED = 'fulfilled';
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
return reject(new TypeError('不能循环引用'));
}
// x为对象或者函数
if ((x !== null && typeof x === 'object') || typeof x === 'function') {
let called = false;
try {
// x为函数
let then = x.then;
if (typeof then === 'function') {
then.call(x,
(y) => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject)
},
(r) => {
if (called) return;
called = true;
reject(r)
},
)
//x为对象
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
// x为普通值
}else {
resolve(x);
}
}
class Promise1 {
constructor(executor) {
this.status = PENDING;
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = (value) => {
if (this.status === FULFILLED) return;
this.value = value;
this.status = FULFILLED;
this.onFulfilledCallbacks.forEach(fn => fn());
}
const reject = (reason) => {
if (this.status === REJECTED) return;
this.reason = reason;
this.status = REJECTED;
this.onRejectedCallbacks.forEach(fn => fn())
}
try {
executor(resolve, reject);
} catch (e) {
reject(e)
}
}
then(onFulfilled, onRejected) {
const promise2 = new Promise1((resolve, reject) => {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : r => reject(r); // If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected with the same reason.
if (this.status === PENDING) {
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
if (this.status === FULFILLED) {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
if (this.status === REJECTED) {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
}
});
return promise2;
}
}
Promise1.deferred = function () {
const dfd = {};
dfd.promise = new Promise1((resolve, reject) => {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise1;
测试
用promises-aplus-tests这包来测试proise代码
下载包
npm install promises-aplus-tests -g
运行测试文件
promises-aplus-tests 文件名
promise其他方法的实现待续
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。