// promise 有一个参数 是一个函数 PromiseA+ 里他叫 execoutor
// 这个函数有两个参数 resolve reject
// PromiseA+规范中规定 : promise 有三个状态 pending fulfilled rejected
// pending (等待状态) 默认初识状态 可以转换为 fulfilled (成功状态) 或者 rejected (失败状态)
// 当转换为 成功 或者 失败 状态后无法转为其他状态
// 成功状态 必须有一个不可改变的值 value
// 失败状态 必须有一个不可改变的原因 reason
// new Promise((resolve,reject)=>{
// resolve(value) // 成功 接收一个value 状态转换为 fulfilled 不可再次改变
// reject(reason) // 失败 接收一个 reason 状态转换为 reason 不可再次改变
// // 当代码抛出异常直接执行 reject
// })
// promiseA+ 规定 要有一个 叫做 then的方法 里面有两个参数 onFulfilled,onRejected 成功有成功的值 失败有失败的原因
// 当状态 state 为 fulfilled 则执行 onFulfilled 传入 this.value 当状态 state为 rejected 则执行 onRejected 传入 this.reason
// onFulfilled, onRejcted 如果他们是函数 则必须分别在 fulfilled, rejected 之后被调用 value或reason 依次作为他们的第一个参数
// 当按照以上要求实现了 一个Promise 类时 promise 就可以简单的使用一下了
// 当 resolve 在 setTimeout内执行 then时 state 还是pending状态
// 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们
// 类似于发布订阅,先将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内。
// 成功或者失败时,forEach调用它们
// 下面就需要解决链式调用了
// promiseA+规定了 then 方法 必须返回一个 promise 并给出了一个示例
// promise2 = promise1.then(onFulfilled, onRejected);
// promiseA=规定 第一个then中返回了一个参数 x 判断x的函数叫做 resolvePromise
// 首先看 x 是不是promise
// 如果是 promise 则取他的结果作为promise2成功的结果
// 所以要比较x 和promise2
// resolvePromise 的参数有 promise2 (默认返回的promise) x 我们自己return的对象 resolve reject
// resolve 和 reject 是 promise2的
// 处理一些参数问题
// A+ 规定 onFulfilled,onRejected都是可选参数,如果他们不是函数,必须被忽略
// onFulfilled返回一个普通的值,成功时直接等于 value => value
// onRejected返回一个普通的值,失败时如果直接等于 value => value,则会跑到下一个then中的onFulfilled中,
// 所以直接扔出一个错误reason => throw err
// A+ 规定onFulfilled或onRejected不能同步被调用,必须异步调用。我们就用setTimeout解决异步问题
// 如果onFulfilled或onRejected报错,则直接返回reject()
class MyPromise {
constructor(executor) {
// 状态 初始化 默认值 pending
this.state = "pending"
// 成功的值
this.value = undefined
// 失败的原因
this.reason = undefined
// 成功存放的数组
this.onResolvedCallbacks = []
// 失败存放的数组
this.onRejectedCallbacks = []
// 成功
let resolve = (value) => {
// 如果状态不是pending 不执行
if (this.state !== "pending") return
// 将状态改变为 fulfilled
this.state = "fulfilled"
// 成功的值
this.value = value
// 一旦 resolve 执行 调用成功数组中的函数
this.onResolvedCallbacks.forEach((fn) => fn())
}
// 失败
let reject = (reason) => {
// 如果状态不是pending 不执行
if (this.state !== "pending") return
// 将状态改变为 rejected
this.state = "rejected"
// 失败的原因
this.reason = reason
// 一旦 reject 执行 调用失败数组的函数
this.onRejectedCallbacks.forEach((fn) => fn())
}
try {
// 立即执行函数
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
// then 方法
then(onFulfilled, onRejected) {
// onfulfilled 如果不是函数 忽略 onfulfilled 直接返回value
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value
// onRejected如果不是函数,就忽略onRejected,直接扔出错误
onRejected =
typeof onRejected === "function"
? onRejected
: (err) => {
throw err
}
// 声明返回的promise2
let myPromise2 = new MyPromise((reslove, reject) => {
// 成功执行 onFulfilled
if (this.state === "fulfilled") {
// 异步
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(myPromise2, x, reslove, reject)
} catch (err) {
reject(err)
}
})
}
// 失败执行 onRejecyed
if (this.state === "rejected") {
// 异步
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(myPromise2, x, reslove, reject)
} catch (err) {
reject(err)
}
})
}
// 当状态为 pending 时 将方法存入各自的数组中
if (this.state === "pending") {
this.onResolvedCallbacks.push(() => {
// 异步
setTimeout(() => {
try {
let x = onFulfilled(this.value)
resolvePromise(myPromise2, x, reslove, reject)
} catch (err) {
reject(err)
}
})
})
this.onRejectedCallbacks.push(() => {
// 异步
setTimeout(() => {
try {
let x = onRejected(this.reason)
resolvePromise(myPromise2, x, reslove, reject)
} catch (err) {
reject(err)
}
})
})
}
})
return myPromise2
}
}
// proimiseA+规范规定了一段代码 让不同的promise代码相互套用 叫做 resolvePromise
// let p = new Promise(resolve => {
// resolve(0);
// });
// var p2 = p.then(data => {
// // 循环引用,自己等待自己完成,一辈子完不成
// return p2;
// })
// 如果 x === promise2 则会造成循环引用 需要自己等待完成 ===> 如果x待处理pending,则promise必须保持待处理状态,直到xfulfilled或rejected为止。
// 判断 x
// x 不能是null
// 如果x是普通对象 直接resolve(x)
// x是对象或者函数包括(promise) let then = x.then 2、当x是对象或者函数(默认promise)
// 声明了 then
// 如果取 then 报错 则走 reject()
// 如果then 是个函数 则用call执行then 第一个参数是this 后面是成功回调和失败的回调
// 如果成功的回调 还是promise 就递归解析 3 成功和失败只能调用一个 所以设定一个called来防止多次调用
function resolvePromise(promise2, x, resolve, reject) {
// 循环引用报错
if (x === promise2) {
return reject(new TypeError("检测到循环引用"))
}
// 防止多次调用
let called
// 如果 x 不是null 并且是函数或者对象
if (x !== null && (typeof x === "object" || typeof x === "function")) {
try {
// A+规定 声明then = x.then方法
let then = x.then
// 如果 then 是函数 就默认是 promise
if (typeof then === "function") {
// 就让then执行 第一个参数是this 后面是成功的回调 和 失败的回调
then.call(
(x, y) => {
// 成功和失败只能调用一个
if (called) return
called = true
// resolve的结果依旧是promise那就继续解析
resolvePromise(promise2, y, resolve, reject)
},
(err) => {
//成功和失败只能调用一个
if (called) return
called = true
// 失败了就直接返回
reject(err)
}
)
} else {
/// 直接成功
resolve(x)
}
} catch (err) {
//也属于失败
if (called) return
called = true
// 取then出错了就不继续了
reject(err)
}
} else {
resolve(x)
}
}
const p = new MyPromise((reslove, reject) => {
setTimeout(() => {
reslove(123)
}, 100)
})
.then((res) => {
console.log(res)
return 444
})
.then((res) => {
console.log(res)
})
// const p1 = new Promise((reslove,reject)=>{
// reslove(444);
// })
// p1.then(value =>{
// console.log(value);
// })
// p1.then(value=>{
// console.log(value);
// })
手写Promise
2023/3/1