在前端开发中,Promise 是常用的异步编程解决方案之一。因此,手写一个 Promise 已经成为了前端面试必考的一道题目。本文将为大家详细介绍如何手写一个 Promise,并给出示例代码和学习以及指导意义。
Promise 的基本概念
Promise 是一种异步编程的解决方案,它可以用来处理异步操作中的回调地狱问题。Promise 是一个对象,它代表了一个异步操作的最终完成或失败的状态以及它的返回值。Promise 有三种状态:pending(等待中)、fulfilled(已完成)和 rejected(已失败)。
手写一个 Promise
下面是手写一个 Promise 的基本步骤:
- 定义一个 Promise 类,并在构造函数中初始化 Promise 的状态为 pending。
- 定义 resolve 和 reject 两个方法,并在方法中将 Promise 的状态改为 fulfilled 或 rejected。
- 在 Promise 类中定义 then 方法,并在方法中判断当前 Promise 的状态,如果是 fulfilled,则执行成功的回调函数;如果是 rejected,则执行失败的回调函数。
- 在 Promise 类中定义 catch 方法,用于捕获 Promise 中的异常。
下面是示例代码:
// www.javascriptcn.com code example
class MyPromise {
constructor(executor) {
this.status = 'pending'
this.value = undefined
this.reason = undefined
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
const resolve = value => {
if (this.status === 'pending') {
this.status = 'fulfilled'
this.value = value
this.onFulfilledCallbacks.forEach(fn => fn())
}
}
const reject = reason => {
if (this.status === 'pending') {
this.status = 'rejected'
this.reason = reason
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : error => { throw error }
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)
}
if (this.status === 'pending') {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return promise2
}
catch(onRejected) {
return this.then(null, onRejected)
}
resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循环引用'))
}
let called = false
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then
if (typeof then === 'function') {
then.call(x, y => {
if (called) return
called = true
this.resolvePromise(promise2, y, resolve, reject)
}, e => {
if (called) return
called = true
reject(e)
})
} else {
resolve(x)
}
} catch (error) {
if (called) return
called = true
reject(error)
}
} else {
resolve(x)
}
}
}学习以及指导意义
手写一个 Promise 对于前端开发者来说是一项必备的技能,因为 Promise 是异步编程的重要解决方案之一。掌握 Promise 的原理和实现方式,可以帮助我们更好地理解异步编程的本质,从而更好地应对异步编程中的各种问题。
在实现 Promise 的过程中,我们需要注意以下几点:
- Promise 的状态只能从 pending 转换为 fulfilled 或 rejected,且状态一旦改变就不能再次改变。
- then 方法可以被调用多次,每次调用都应该返回一个新的 Promise 对象。
- then 方法中的回调函数可以返回一个值或一个新的 Promise 对象。
- then 方法中的回调函数应该异步执行,以避免阻塞主线程。
除此之外,我们还需要了解 Promise 中的一些常用方法,比如 all、race、finally 等,以及 Promise 的错误处理方式。总之,学习 Promise 对于我们提高前端开发能力和应对面试挑战都具有重要的意义。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d95fa9a941bf71340f7676