您现在的位置是:网站首页 > 手写Promise面试题文章详情
手写Promise面试题
陈川 【 JavaScript 】 8608人已围观
在JavaScript中,Promise
是一个用于异步编程的对象,代表了未来可能完成或失败的操作的结果。它可以处于三种状态之一:pending(等待中)、fulfilled(已完成)或rejected(已拒绝)。一旦Promise
被解决(无论是完成还是拒绝),它将保持在该状态,不会再改变。
Promise的基本使用
在标准JavaScript中,创建一个Promise
对象通常如下所示:
const promise = new Promise((resolve, reject) => {
// 异步操作
setTimeout(() => {
const result = '异步操作成功';
resolve(result); // 成功时调用resolve
}, 1000);
});
我们可以使用.then()
和.catch()
方法来处理Promise
的成功和失败情况:
promise
.then(result => {
console.log('成功结果:', result);
})
.catch(error => {
console.error('错误信息:', error);
});
手写Promise
接下来,我们将从零开始构建一个简单的Promise
实现。首先定义一个MyPromise
构造函数,它接受一个执行器作为参数,这个执行器接收resolve
和reject
两个函数作为参数:
function MyPromise(executor) {
let state = 'pending';
let value = null;
let reason = null;
let onFulfilledCallbacks = [];
let onRejectedCallbacks = [];
function resolve(val) {
if (state === 'pending') {
state = 'fulfilled';
value = val;
onFulfilledCallbacks.forEach(fn => fn());
}
}
function reject(err) {
if (state === 'pending') {
state = 'rejected';
reason = err;
onRejectedCallbacks.forEach(fn => fn());
}
}
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
为了使我们的MyPromise
可以链式调用,我们需要实现then
方法:
MyPromise.prototype.then = function(onFulfilled, onRejected) {
onFulfilled =
typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected =
typeof onRejected === 'function'
? onRejected
: reason => { throw reason; };
let promise2 = new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
} else {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
};
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
let called;
if ((x instanceof MyPromise)) {
if (x.state === 'pending') {
x.then(y => resolvePromise(promise2, y, resolve, reject), reject);
} else {
x.then(resolve, reject);
}
} else if (x && (typeof x === 'object' || typeof x === 'function')) {
try {
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);
}
);
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
在这个实现中,我们还添加了对Promise.all
的支持,以便能够同时处理多个Promise
:
MyPromise.all = function(promises) {
return new MyPromise((resolve, reject) => {
let results = [];
let count = 0;
promises.forEach((promise, index) => {
promise.then(value => {
results[index] = value;
count++;
if (count === promises.length) {
resolve(results);
}
}, reject);
});
});
};
结论
通过手动实现Promise
,我们不仅加深了对异步编程的理解,还掌握了Promise
的工作原理和内部结构。虽然我们的MyPromise
实现较为基础,但它涵盖了Promise
的核心功能,包括状态管理、异步操作的处理以及链式调用。在实际项目中,你可能不会需要自己实现Promise
,但在理解其底层逻辑后,你将能够更加自信地使用原生Promise
API,从而编写出更高效、更可维护的代码。
站点信息
- 建站时间:2017-10-06
- 网站程序:Koa+Vue
- 本站运行:
- 文章数量:
- 总访问量:
- 微信公众号:扫描二维码,关注我