好,我们今天来手写Promise
/*
1.Promise 是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
2.Promise 有三种状态 分别为 成功(fulfilled) 失败(rejected) 等待(pending)
pending -> fulfilled
pending -> rejected
一旦状态确定就不可更改
3.resolve 跟 reject 就是用来更改状态的,resolve 就是把状态改为 fulfilled,reject就是把状态
改为 rejected
4.then 方法内部做的事情就是判断状态,如果状态时成功,调用成功回调函数,如果状态时失败,调用失败回调函数.then 方法是被定义在原型对象中的
5.then 成功回调函数有一个参数,表示成功之后的值,then 失败回调也有一个参数,表示失败的原因
6. 同一个promise对象下面的then方法是可以被调用多次的
7. then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
*/
let promise = new Promise((resolve,reject) => {
resolve('成功')
reject('失败')
})
promise.then(value => {}, reason => {})
//开搞开搞
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise {
constructor (executor) {
//捕获执行器中的错误
try{
executor(this.resolve,this.reject)
}catch(e){
this.reject(e)
}
}
status = PENDING
value = undefined
reason = undefined
// 成功回调,同一个promise对象的then方法可以多次调用,所以在异步的情况下,要用数组来存储成功回调或者失败回调
successCallback = []
// 失败回调
failCallback = []
// 定义 resolve 跟 reject
// 因为以后调用 resolve 或者 reject 是直接调用的,如果用普通函数的写法的话,这个函数的 this 会指向 window 或者 undefined,所以要用箭头函数来让 this 指向 MyPromise 的实例对象
resolve = value => {
//如果状态不是 pending,阻止程序向下执行
if(this.status !== PENDING) return
//将状态更改为成功
this.status = FULFILLED
//保存成功之后的值
this.value = value
//判断成功回调是否存在,如果存在就调用
//this.successCallback && this.successCallback()
while(this.successCallback.length) {
this.successCallback.shift()()
}
}
reject = reason => {
//如果状态不是 pending,阻止程序向下执行
if(this.status !== PENDING) return
//将状态更改为失败
this.status = REJECTED
//保存失败的原因
this.reason = reason
//判断失败回调是否存在,如果存在就调用
//this.failCallback && this.failCallback(this.reason)
while(this.failCallback.length) {
this.failCallback.shift()()
}
}
then (successCallback,failCallback) {
//判断 then 是否有参数
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => {throw reason}
let promise2 = new MyPromise((resolve, reject) =>{
//判断状态
if (this.status === FULFILLED) {
setTimeout(() => {
//捕获成功回调的错误
try{
let suc = successCallback(this.value)
//判断 suc 的值是普通值还是 promise 对象
//如果是普通值,直接调用 resolve
//如果是 promise 对象,查看 promise 对象返回的结果
//再根据 promise 对象返回的结果,决定调用 resolve 还是调用 reject
resolvePromise(promise2, suc, resolve, reject)
}catch(e){
reject(e)
}
})
}else if(this.status === REJECTED) {
setTimeout(() => {
//捕获失败回调的错误
try{
let fail = failCallback(this.reason)
//判断 fail 的值是普通值还是 promise 对象
//如果是普通值,直接调用 resolve
//如果是 promise 对象,查看 promise 对象返回的结果
//再根据 promise 对象返回的结果,决定调用 resolve 还是调用 reject
resolvePromise(promise2, fail, resolve, reject)
}catch(e){
reject(e)
}
})
}else {//等待状态,此为在执行 MyPromise 时异步调用了resolve,所以才会有等待状态
this.successCallback.push(() => {
setTimeout(() => {
//捕获成功回调的错误
try{
let suc = successCallback(this.value)
//判断 suc 的值是普通值还是 promise 对象
//如果是普通值,直接调用 resolve
//如果是 promise 对象,查看 promise 对象返回的结果
//再根据 promise 对象返回的结果,决定调用 resolve 还是调用 reject
resolvePromise(promise2, suc, resolve, reject)
}catch(e){
reject(e)
}
})
})
this.failCallback.push(()=>{
setTimeout(() => {
//捕获失败回调的错误
try{
let fail = failCallback(this.reason)
//判断 fail 的值是普通值还是 promise 对象
//如果是普通值,直接调用 resolve
//如果是 promise 对象,查看 promise 对象返回的结果
//再根据 promise 对象返回的结果,决定调用 resolve 还是调用 reject
resolvePromise(promise2, fail, resolve, reject)
}catch(e){
reject(e)
}
})
})
}
})
return promise2
}
finally (callback) {
return this.then((value) => {
return MyPromise.resolve(callback()).then(() => value)
}, (reason) =>{
return MyPromise.resolve(callback()).then(() => {throw reason})
})
}
catch (failCallback) {
return this.then(undefined, failCallback)
}
static all (array) {
let result = []
let index = 0
return new MyPromise((resolve, reject) => {
function addData (key, value) {
result[key] = value
// 考虑到异步的情况,所以要用计数器来保证数组里所有的Promise执行完成了再调用resolve
index++
if (index === array.length) {
resolve(result)
}
}
for(let i = 0; i < array.length; i++) {
let current = array[i]
if(current instanceof MyPromise){
// MyPromise 对象
current.then(value => addData(i, value), reason => reject(reason))
}else {
//普通值
addData(i, array[i])
}
}
})
}
static race (array) {
return new MyPromise((resolve, reject) => {
array.forEach(item => {
if(item instanceof MyPromise){
item.then(value => resolve(value), reason => reject(reason))
}else {
resolve(item)
}
})
})
}
static resolve (value) {
if (value instanceof MyPromise) {
return value
}else {
return new MyPromise(resolve => resolve(value))
}
}
}
function resolvePromise(promise2, value, resolve, reject) {
//判断是否promise对象自返回
if(promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (value instanceof MyPromise) {
value.then(resolve, reject)
} else {
resolve(value)
}
}