让我们来详细讲解“JavaScript面试必备技巧之手写一个Promise”的完整攻略。
什么是Promise
Promise 是一种处理异步操作的方式,是 ES6 中新增的 JavaScript 特性。Promise 是异步编程的一种解决方案,用于解决回调地狱问题。
Promise的三种状态
一个 Promise 有三种状态:pending(初始状态)、fulfilled(成功状态)和 rejected(失败状态)。
- pending:Promise 实例被创建后,处于初始状态,既未成功,也未失败;
- fulfilled:成功状态,表示 Promise 操作成功完成,将返回相应的结果值,该状态下 Promise 不能变为其它状态;
- rejected:失败状态,表示 Promise 操作未成功完成,并且返回了相应的原因,该状态下 Promise 不能变为其它状态。
手写Promise
以下是手写一个 Promise 的步骤:
- 定义Promise的构造函数
class MyPromise {
constructor(executor) {
// executor为自定义函数,有 resolve 和 reject 两个参数
this.status = 'pending'; // Promise对象的初始状态
this.value = undefined; // Promise对象的返回值
this.reason = undefined; // Promise对象的失败原因
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
}
- 实现 Promise 的 resolve 和 reject 函数
class MyPromise {
constructor(executor) {
// 省略代码
// resolve函数,将 Promise 状态从 pending 改为 fulfilled,同时返回最终处理结果
this.resolve = value => {
if (this.status === 'pending') {
this.status = 'fulfilled';
this.value = value;
}
}
// reject函数,将 Promise 状态从 pending 改为 rejected,同时返回失败原因
this.reject = reason => {
if (this.status === 'pending') {
this.status = 'rejected';
this.reason = reason;
}
}
}
}
- 实现 Promise 的 then 方法
class MyPromise {
constructor(executor) {
// 省略代码
// then函数,用于异步调用
this.then = (onFulfilled, onRejected) => {
if (this.status === 'fulfilled') {
onFulfilled(this.value);
}
if (this.status === 'rejected') {
onRejected(this.reason);
}
}
}
}
- 完善 Promise 的异常处理机制
class MyPromise {
constructor(executor) {
// 省略代码
// 当Promise产生异常时,将状态改为rejected
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
// then方法要返回一个新的 Promise 实例,因此需在 then 中创建新的 Promise
// 用来异步执行 onFulfilled 和 onRejected 函数
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; }
const promise2 = new MyPromise((resolve, reject) => {
if (this.status === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
if (this.status === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
this.resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
}
});
return promise2;
}
// 添加resolvePromise方法,用于处理then回调函数返回值的情况
resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called = false;
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
this.resolvePromise(promise2, y, resolve, reject);
}, r => {
if (called) return;
called = true;
reject(r);
})
} else {
resolve(x)
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}
}
示例说明
示例一
const promise = new MyPromise(resolve => {
console.log('start promise 1');
setTimeout(() => resolve('promise 1'), 1000);
})
promise.then(res => {
console.log(res);
})
console.log('end');
当执行以上示例代码时,会先输出 'start promise 1'
和 'end'
,1秒后输出 'promise 1'
。这是因为 promise 对象是异步执行的,而 then 函数就是异步的。执行 promise 对象的构造函数不会阻塞主线程,只有当 promise 对象的相关操作发生时,才会异步执行 then 函数中的回调函数。
示例二
const promise = new MyPromise(resolve => {
console.log('start promise 2');
setTimeout(() => {
resolve('promise 2');
}, 1000);
}).then(res => {
console.log(1);
return res;
}).then(res => {
console.log(2);
return res;
}).then(res => {
console.log(3);
return res;
});
console.log('end');
当执行以上示例代码时,会先输出 'start promise 2'
和 'end'
,然后等待 1 秒后输出 1
,再等待 1 秒后输出 2
,最后输出 3
。这是因为当一个 promise 对象链式调用多个 then 方法时,每个 then 方法返回一个新的 Promise 对象,用来串联每个回调函数的返回结果,形成一个 promise 链式调用过程。因此在执行 then 方法前,promise 对象并不会停止,而是继续执行,直到 promise 对象完成操作后,才会继续执行 then 中的回调函数。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript面试必备技巧之手写一个Promise - Python技术站