1.什么是promise?promise解决了什么问题?
Promise是 JavaScript 中处理异步操作的一种机制,它可以让异步操作更加可控、易于管理。 在 JavaScript 中,许多操作都是异步的,比如网络请求、读取文件等。异步操作通常会导致代码变得复杂,因为你需要正确地处理回调函数,处理错误等等。为了解决这个问题,Promise 在 ECMAScript 6 (ES6) 中被引入。
- 顺序控制:使用 Promise,你可以通过 then 方法按照顺序执行异步操作,使得代码的执行流程更加清晰,而不需要嵌套多层的回调函数(这也被称为“回调地狱”)。
- 错误处理:Promise 提供了 catch 方法,可以用来统一处理异步操作中发生的错误,避免错误冒泡到全局作用域。
- 避免回调地狱:Promise 可以解决传统的回调函数嵌套问题,让代码更易于理解和维护。
- 更容易的异步编程:使用 Promise,你可以更容易地组织和管理异步代码,可以使用 Promise.all 和 Promise.race 来处理多个异步操作,以及进行并发控制等等。
- 更容易进行错误处理和调试:Promise 提供了明确的错误处理机制,让你可以很容易地找到并解决异步操作中的问题。
// 定义promise状态常量
const PENGDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
// 声明私有属性 #
#state = PENGDING
#result = undefined
#hanlders = []
constructor(executor) {
// 调用对应函数改变状态,初始状态为pending
// promise的状态一但改变就是不可再变的了
const resolve = (data) => {
// if (this.#state !== PENGDING) return
// this.#state = FULFILLED
// this.#result = data
this.#changeState(FULFILLED, data)
}
const reject = (reason) => {
// if (this.#state !== PENGDING) return
// this.#state = REJECTED
// this.#result = reason
this.#changeState(REJECTED, reason)
}
// promise 无法捕获异步错误
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
#changeState(state, result) {
if (this.#state !== PENGDING) return
this.#state = state
this.#result = result
console.log(this.#state, this.#result)
// 当promise状态改变执行run
}
// 接收两个回调,一个失败的回调,一个成功的回调
// then方法返回的还是一个promise
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
this.#hanlders.push({
onFulfilled,
onRejected,
resolve,
reject,
})
this.#run()
})
}
catch(onRejected) {
return this.then(null, onRejected)
}
#isPromiseAPlus(obj) {
return (
typeof obj === 'object' &&
obj !== null &&
typeof obj.then === 'function' &&
typeof obj.catch === 'function'
)
}
// 使用 setTimeout 来模拟微任务,确保了异步任务的执行
#runMicroTask(func) {
setTimeout(func, 0)
}
#runOne(callback, resolve, reject) {
this.#runMicroTask(() => {
if (typeof callback !== 'function') {
const settled = this.#state === FULFILLED ? resolve : reject
settled(this.#result)
return
}
try {
const data = callback(this.#result)
if (this.#isPromiseAPlus(data)) {
data.then(resolve, reject)
} else {
resolve(data)
}
} catch (error) {
reject(error)
}
}, 0)
}
#run() {
if (this.#state === PENGDING) return
// 当前promise状态===FULFILLED
while (this.#hanlders.length) {
const { onFulfilled, onRejected, resolve, reject } =
this.#hanlders.shift()
/**
* 1.什么时候该调用resolve,reject?有以下三种情况
* 对应的回调不是函数
* 回调是函数
* 回调是promise
*/
if (this.#state === FULFILLED) {
this.#runOne(onFulfilled, resolve, reject)
// if (typeof onFulfilled === 'function') {
// // 当回调是函数时,try catch 捕获错误
// try {
// const data = onFulfilled(this.#result)
// resolve(data)
// } catch (error) {
// reject(error)
// }
// } else {
// // 当回调不是函数时,promise执行穿透
// resolve(this.#result)
// }
} else if (this.#state === REJECTED) {
this.#runOne(onRejected, resolve, reject)
// if (typeof onRejected === 'function') {
// // 当回调是函数时,try catch 捕获错误
// try {
// const data = onRejected(this.#result)
// resolve(data)
// } catch (error) {
// reject(error)
// }
// } else {
// // 当回调不是函数时,promise执行穿透
// reject(this.#result)
// }
}
}
}
}
let myPromise = new MyPromise((resolve, reject) => {
resolve('123')
})
myPromise.then((res) => {
console.log(res)
})
myPromise.then((res) => {
console.log(res)
})
myPromise
.then(null, (err) => {
console.log(err)
})
.then((data) => {
console.log('data', data)
})
2.以上部分代码来自于袁进老师
此篇文章仅用于个人知识点记录。袁老师个人blog: blog.yuanjin.tech/