Promise
说到promise,大家都不会陌生。现在面试基本都会遇到promise的问题,废话不多说,本篇就来一步步解析,带大家写一个自己的promise。
初始化项目
新建一个文件夹,来作为项目目录,在目录下创建两个文件
- index.js (作为主程序
- myPromise.js (写我们的promise类
mkdir promise-demo
cd promise-demo
touch index.js
touch myPromise.js
小伙伴们,我们的项目文件初始化工作就做好了,接下来,我们开始规划一下promise类,看看他会实现什么功能,这些功能又怎么对应的编写成类方法。
promise类
先上代码
// 定义各状态值
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECT = 'reject'
// myPromise是一个类
class myPromise {
// 构造方法中调用实例化时传入的执行器 并将两个原型方法传递给执行器
constructor (exer) {
// 为了捕获错误
try {
exer(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
// 初始化状态值为等待
status = PENDING
// 初始化成功和失败的值
successData = undefined
failReason = undefined
successFunc = []
failFunc = []
// 使用箭头函数 this指向实例化后的myPromise实例对象
resolve = (data) => {
// 判断是否状态是PENDING 否则返回
if (this.status !== PENDING) return
this.status = FULFILLED
this.successData = data
// 循环调用
while(this.successFunc.length) this.successFunc.shift()()
}
reject = (reason) => {
// 判断是否状态是PENDING 否则返回
if (this.status !== PENDING) return
this.status = REJECT
this.failReason = reason
while(this.failFunc.length) this.failFunc.shift()()
}
then = (resolve, reject) => {
// then可变参
resolve = resolve ? resolve : value => value
reject = reject ? reject : reason => { throw reason}
// 每一个then之后都会返回一个myPromise对象 以进行链式调用
let promise2 = new myPromise((successCallBack, failCallBack) => {
// 立即执行的代码
switch (this.status) {
case FULFILLED:
// 如果已经触发了resolve 直接执行传入方法
// resolve(this.successData)
// 由于链式调用 这里会返回promise或者值或空
// 我们需要在执行完resolve后按结果调用下一个then的resolve或reject,
// 也就是这个返回的promise的successCallBack,和failCallBack
setTimeout(()=> {
try{
let x = resolve(this.successData)
// 这个x就是执行完resolve后的返回
solvePromise(promise2, x, successCallBack, failCallBack)
} catch (error) {
failCallBack(error)
}
}, 0)
break;
case REJECT:
setTimeout(()=> {
try{
let x = reject(this.failReason)
solvePromise(promise2, x, successCallBack, failCallBack)
} catch (error) {
failCallBack(error)
}
}, 0)
break;
case PENDING:
// 如果是等待的状态 把方法存进数组 以进行多次调用
this.successFunc.push(() => {
setTimeout(()=> {
try{
let x = resolve(this.successData)
// 这个x就是执行完resolve后的返回
solvePromise(promise2, x, successCallBack, failCallBack)
} catch (error) {
failCallBack(error)
}
}, 0)
})
this.failFunc.push(() => {
setTimeout(()=> {
try{
let x = reject(this.failReason)
solvePromise(promise2, x, successCallBack, failCallBack)
} catch (error) {
failCallBack(error)
}
}, 0)
})
default:
break;
}
})
return promise2
}
catch (failCallBack) {
this.then(undefined, failCallBack)
}
finally (cb) {
return this.then(value => {
cb()
return value
}, reason => {
cb()
throw reason
})
}
static resolve (value) {
if (value instanceof myPromise) return value
return new myPromise(resolve => resolve(value))
}
static all = (array) => {
let list = []
let index = 0
return new myPromise((resolve, reject) => {
function addData (key, value) {
console.log(key, value)
list[key] = value
index++
if (index === array.length) {
resolve(list)
}
}
for (let i = 0; i< array.length; i++) {
let pro = array[i]
if (pro instanceof myPromise ) {
pro.then(value => addData(i, value))
} else {
addData(i, pro)
}
}
})
}
}
function solvePromise (promise, x, resolve, reject) {
if (promise === x) {
return reject(new TypeError('哥们 这你咋还返回当前的promise呢'))
}
if (x instanceof myPromise) {
// 如果是一个myPromise的返回 比如是一个ajax请求 调用它的then方法
// 并按实际执行的情况 调用返回的myPromise实例的successCallBack或failCallBack
x.then(resolve, reject)
} else {
// 如果是值 直接执行resolve 如果是空 透传
resolve(x)
}
}
module.exports = myPromise
调用
let myPromise = require('./myPromise')
let process = new myPromise((resolve, reject) => {
})