Promise
• #js
Promise出现解决了什么问题
- 处理异步函数,返回的结果给到的是setTimeout,给不到外层函数需要自己去设计好回调函数 ◭ 自己设计的回调函数
Promise的基本使用
Promise是一个类
入参为函数(称为executor,立即执行)
resolve 成功时回调
reject 失败时回调
◭ Promise的基本使用
Promise的三种状态
- pending
- fulfilled
- rejected ◭ Promise的三种状态
Promise的对象方法
- then
- catch
- finally 最终状态不论是fulfilled还是rejected,都会执行finally
可以被多次调用,Promise状态由回调函数的返回值决定
Promise的类方法
- resolve
- reject
- all 有一个Promise状态为rejected就会中断,根据数组的顺序了不按照时间返回结果
- allSettled 返回所有的状态和结果
- race 最快的
- any 等到一个fulfilled结果 ◭ Promise的类方法
手写Promise
Promise的结构设计
Promise类包含一个State和Result
构造函数里面的函数私有,class类里面的函数公共
// 定义resolve,reject函数
// 执行传入的executor函数,并传入resolve和reject作为参数
// 执行 executor 函数:
// 调用resolve,reject函数
// 构造函数执行完毕,afe1实例创建完成
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'
class Afe1Promise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
const resolve = (value) => {
if (this.status === PROMISE_STATUS_PENDING) {
this.status = PROMISE_STATUS_FULFILLED
this.value = value
console.log("resolve被调用")
}
}
const reject = (reason) => {
if(this.status === PROMISE_STATUS_PENDING){
this.status = PROMISE_STATUS_REJECTED
this.reason = reason
console.log('reject被调用');
}
}
executor(resolve,reject)
}
}
const afe1 = new Afe1Promise((resolve,reject) => {
console.log('executor立刻执行');
resolve('调用构造函数里面的resolve函数');
reject('调用构造函数里面的reject函数')
})
◭ Promise的结构设计
Promise-then方法实现
then方法设计
实例调用then方法将传入的onFulfilled和onRejected回调函数直接赋值给了this.onFulfilled和this.onRejected,给实例属性添加了两个函数(主任务)
在构造函数中,当Promise状态改变时,会调用这些存储的回调函数(微任务)
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'
class Afe1Promise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
const resolve = (value) => {
if (this.status === PROMISE_STATUS_PENDING) {
this.status = PROMISE_STATUS_FULFILLED
queueMicrotask(() => {
this.value = value
this.onFulfilled(this.value)
})
}
}
const reject = (value) => {
if(this.status === PROMISE_STATUS_PENDING){
this.status = PROMISE_STATUS_REJECTED
queueMicrotask(() => {
this.reason = value
this.onRejected(this.reason)
})
}
}
executor(resolve,reject)
}
then(onFulfilled,onRejected){
this.onFulfilled = onFulfilled
this.onRejected = onRejected
}
}
const afe1 = new Afe1Promise((resolve,reject) => {
console.log('executor立刻执行');
resolve('调用构造函数里面的resolve函数');
})
afe1.then((res) => {
console.log('then回调函数执行了');
console.log(res);
})
◭ then方法设计
then方法设计优化一
实现多次then调用,确保status状态只能改变一次
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'
class Afe1Promise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
this.onFulfilledFns = []
this.onRejectedFns = []
const resolve = (value) => {
if (this.status === PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_FULFILLED
this.value = value
this.onFulfilledFns.forEach((fn) => {
fn(this.value)
})
})
}
}
const reject = (reason) => {
if(this.status === PROMISE_STATUS_PENDING){
queueMicrotask(() => {
if (this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_REJECTED
this.reason = reason
this.onRejectedFns.forEach((fn) => {
fn(this.reason)
})
})
}
}
executor(resolve,reject)
}
then(onFulfilled,onRejected){
if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
onFulfilled(this.value)
}
if(this.status === PROMISE_STATUS_REJECTED && onRejected){
onRejected(this.reason)
}
if(this.status === PROMISE_STATUS_PENDING){
this.onFulfilledFns.push(onFulfilled)
this.onRejectedFns.push(onRejected)
}
}
}
const afe1 = new Afe1Promise((resolve,reject) => {
console.log('executor立刻执行');
resolve('调用构造函数里面的resolve函数');
})
afe1.then((res) => {
console.log('then回调函数执行了1');
console.log(res);
})
afe1.then((res) => {
console.log('then回调函数执行了2');
console.log(res);
})
// 在确定Promise状态之后, 再次调用then
setTimeout(() => {
afe1.then(res => {
console.log("res3:", res)
}, err => {
console.log("err3:", err)
})
}, 1000)
◭ then方法设计优化一
then方法设计优化二
实现then的链式调用(之前是调用then方法传入的函数,现在调用的是包装的函数)
const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'
class Afe1Promise {
constructor(executor){
this.status = PROMISE_STATUS_PENDING
this.value = undefined
this.reason = undefined
this.onFulfilledFns = []
this.onRejectedFns = []
const resolve = (value) => {
if (this.status === PROMISE_STATUS_PENDING) {
queueMicrotask(() => {
if (this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_FULFILLED
this.value = value
this.onFulfilledFns.forEach((fn) => {
fn(this.value)
})
})
}
}
const reject = (reason) => {
if(this.status === PROMISE_STATUS_PENDING){
queueMicrotask(() => {
if (this.status !== PROMISE_STATUS_PENDING) return
this.status = PROMISE_STATUS_REJECTED
this.reason = reason
this.onRejectedFns.forEach((fn) => {
fn(this.reason)
})
})
}
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled,onRejected){
return new Afe1Promise((resolve,reject) => {
if(this.status === PROMISE_STATUS_FULFILLED && onFulfilled){
try {
const value = onFulfilled(this.value)
resolve(value)
} catch(err) {
reject(err)
}
}
if(this.status === PROMISE_STATUS_REJECTED && onRejected){
try {
const reason = onRejected(this.reason)
resolve(reason)
} catch(err) {
reject(err)
}
}
if(this.status === PROMISE_STATUS_PENDING){
this.onFulfilledFns.push(() => {
try {
const value = onFulfilled(this.value)
resolve(value)
} catch(err) {
reject(err)
}
})
this.onRejectedFns.push(() => {
try {
const reason = onRejected(this.reason)
resolve(reason)
} catch(err) {
reject(err)
}
})
}
})
}
}
const afe1 = new Afe1Promise((resolve,reject) => {
console.log('executor立刻执行');
resolve('调用构造函数里面的resolve函数');
})
afe1.then((res) => {
console.log('then回调函数执行了1');
console.log(res);
})
afe1.then((res) => {
console.log('then回调函数执行了2');
console.log(res);
})
// 在确定Promise状态之后, 再次调用then
setTimeout(() => {
afe1.then(res => {
console.log("res3:", res)
}, err => {
console.log("err3:", err)
})
}, 1000)
// 调用then方法多次调用
afe1.then(res => {
console.log("res1:", res)
return "aaaa"
// throw new Error("err message")
}, err => {
console.log("err1:", err)
return "bbbbb"
// throw new Error("err message")
}).then(res => {
console.log("res2:", res)
}, err => {
console.log("err2:", err)
})
◭ then方法设计优化二