当我们看到这个问题时我们就要想起来什么是promise,promsie该怎么用,解决什么问题的
认识promise
Promise 是 JavaScript 中用于处理异步操作的一种机制。它代表一个异步操作的最终完成(或失败)及其结果值。Promise 的主要目的是解决传统的回调地狱(Callback Hell)问题,使异步代码更易读、更易维护。
promise的用法
既然我们已经知道了promsie是什么,接下来我们来看看promsie该怎么用
function A() {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("A");
resolve()
}, 1000);
})
}
function B() {
console.log("B");
}
A()
.then(() => {
B()
})
这段代码很简单,打印结果为A B如果没有promise,根据事件循环机制,耗时代码分为微任务和宏任务,先执行同步代码再执行异步代码,所以B会先A打印.有了promise,可以通过resolve, reject改变promsie对象的pending状态,状态改变再后再执行.then内的函数.注意resolve()和rejecte()里是可以带参数的
一个 Promise 对象有三种状态:
- Pending(进行中) :初始状态,既不是成功,也不是失败。
- Fulfilled(已成功) :表示操作成功完成。
- Rejected(已失败) :表示操作失败。
一旦 Promise 的状态从 Pending 变为 Fulfilled 或 Rejected,就不会再改变。
Promise 对象有两个主要方法:
.then():用于处理 Fulfilled 状态的结果。.catch():用于处理 Rejected 状态的错误。
手写promise
class MyPromise {
constructor(executor) {
this.status = 'pending' // 状态
this.value = null // 成功的结果
this.reason = null // 失败的结果
this.onFulfilledCallbacks = [] // 存放成功的回调函数
this.onRejectedCallbacks = [] // 存放失败的回调函数
const resolve = (value) => {
if (this.status === 'pending') {
this.value = value
this.status = 'fulfilled'
this.onFulfilledCallbacks.forEach(fn => fn(value))
}
}
const reject = (reason) => {
if (this.status === 'pending') {
this.reason = reason
this.status = 'rejected'
this.onRejectedCallbacks.forEach(fn => fn(reason))
}
}
executor(resolve, reject)
}
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
// 返回一个新的promise对象
let newPromise = new MyPromise((resolve, reject) => {
if (this.status === 'fulfilled') {
setTimeout(() => {
try {
const result = onFulfilled(this.value) // 作为异步任务
if (result instanceof MyPromise) {
newPromise = result
}
resolve(result)
} catch (error) {
reject(error)
}
});
}
if (this.status === 'rejected') {
setTimeout(() => {
try {
const result = onRejected(this.reason) // 作为异步任务
if (result instanceof MyPromise) {
newPromise = result
}
resolve(result)
} catch (error) {
reject(error)
}
});
}
if (this.status === 'pending') {
this.onFulfilledCallbacks.push((value) => {
setTimeout(() => {
try {
const result = onFulfilled(value)
if (result instanceof MyPromise) {
newPromise = result
}
resolve(result)
} catch (error) {
reject(error)
}
})
})
this.onRejectedCallbacks.push((reason) => {
setTimeout(() => {
try {
const result = onRejected(reason)
if (result instanceof MyPromise) {
newPromise = result
}
resolve(result)
} catch (error) {
reject(error)
}
})
})
}
})
return newPromise
}
}
首先new promise中要接受一个回调函数作为参数放到构造器中,初始状态为pending,又因为resolve和reject可以传参,this.value = null 和this.reason = null 分别存结果.this.onFulfilledCallbacks = [] , this.onRejectedCallbacks = [] 分别存回调结果.resolve和reject函数就很简单,将promise对象的状态进行变更,再执行数组中的回调函数.
then函数和catch函数:
then的原理:
- 接收两个参数,一个是成功的回调函数,另一个是失败的回调函数
- 返回一个promise对象
- 当执行到then的时候,then前面的promise状态已经变更为fulfilled或rejected,则会立即执行then中的回调函数
- 当执行到then的时候,then前面的promise状态还是pending,则会将回调函数存储起来,等到前面promise的状态变更为fulfilled或rejected时,再执行回调函数
then其实是可以接受两个参数(都是函数),第二个就是catch的功能. 先进行类型判断,如果进来的参数是函数体就不做修改,如果不是就放一个没意义的函数体.Rejected是会报错的所以要抛出错误;因为then后面还开会接.then所以也要返回一个promise对象.在里面判断第一个函数的状态(通过隐式绑定规则);接下来就是要将then里面的函数进行调用了;但是如果直接调用就是当做同步任务触发,根据事件循环机制是要把.then当中异步任务触发;所以我们用同为异步任务的定时器来包裹一下.还有我们要考虑.then()里面的函数是否有返回对象,如果有返回对象且返回的是promise对象,我们就要返回它自己的promise对象.