promise是基于发布订阅模式,它是一个类,有3个状态,pending(默认等待状态)、resolve(成功)、reject(失败),只用在pending的时候,状态才能改变。promise.then方法是执行函数执行后的回调函数执行收集,promise调用执行如下:
const promise = new Promise((resolve,reject) => {
resolve('ok')
})
promise.then((data) => { // 有两个参数1成功2失败
console.log(data)
},(error) => {
console.log(error)
})
// 打印出ok
基础源码如下:
// 三个状态
const PENDING = 'PENDING' // 默认状态
const FULFILLED = 'FULFILLED' // 成功
const REJECT = 'REJECT' // 失败
class myPromise{
constructor(exector) { // exector执行器,是一个方法,默认立即执行
this.state = PENDING
this.successData = undefined // 保存成功的信息
this.errorData = undefined // 保存失败的信息
// 改变状态
const resolve = (value) => {
if (this.state === PENDING)
this.successData = value
this.state = FULFILLED
}
const reject = (error) => {
this.errorData = error
this.state = REJECT
}
exector(resolve, reject) // 执行器有两个参数,resolve,reject
}
then(resolveFn, rejectFn) {
// 获取到数据,成功的数据,还是失败的数据
if (this.state === FULFILLED) {
return resolveFn(this.successData)
}
if (this.state === REJECT) {
return rejectFn(this.errorData)
}
}
}
下面解决promise里的执行函数是异步的情况,在执行then方法时,在等待的状态中,报执行的方法受集起来,promise类里面定义2个变量resolveList(收集获取成功数据的方法),rejectList(收集获取数据失败的方法),执行成功方法resolve时,遍历resolveList数组执行,执行失败方法reject时,遍历rejectList数组执行,并传入获得的相应数据,代码如下:
// 三个状态
const PENDING = 'PENDING' // 默认状态
const FULFILLED = 'FULFILLED' // 成功
const REJECT = 'REJECT' // 失败
class myPromise{
constructor(exector) { // exector执行器,是一个方法,默认立即执行
this.state = PENDING
this.successData = undefined // 保存成功的信息
this.errorData = undefined // 保存失败的信息
this.resolveList = []
this.rejectList = []
// 改变状态
const resolve = (value) => {
if (this.state === PENDING)
this.successData = value
this.state = FULFILLED
this.resolveList.forEach(fn => fn(this.successData))
}
const reject = (error) => {
this.errorData = error
this.state = REJECT
this.rejectList.forEach(fn => fn(this.successDerrorDataata))
}
exector(resolve, reject) // 执行器有两个参数,resolve,reject
}
then(resolveFn, rejectFn) {
// 获取到数据,成功的数据,还是失败的数据
if (this.state === FULFILLED) {
resolveFn(this.successData)
}
if (this.state === REJECT) {
rejectFn(this.errorData)
}
if (this.state === PENDING) {
this.rejectList.push(rejectFn)
this.resolveList.push(resolveFn)
}
}
}
链式调用,解决地狱回调的问题。then方法中成功回调或者失败的回调,返回一个promise,这个promise就会采用返回promise成功或者失败的值,传递到下一个then中,的成功回调或者失败的回调,返回的是一个普通的值(不是promise),走下一个then中成功的回调,then方法中,成功回调或者失败的回调在执行的时候出现错误,走下一个then中的失败的回调。
- 1、then返回的是一个常量promise,exector是一个立即执行函数,所以把then里面的执行函数内容放到promise里的exector里,把新建的myPromise对象的exector执行内容是第一个myPromise的then方法里面的执行内容,把第一个myPromise里面then的获取成功和失败数据执行的函数添加到对应的resolveList与rejectList中,then里面的新建的myPromise的then方法放到相应的新建的myPromise函数作用遇对象上,如果第一个myPromise状态改变,将会遍历执行第一个函数作用域里的resolveList与rejectList中的函数,执行函数代码里有第二个myPromise对象里的改变状态的resolve与reject函数,执行过程中,第二个myPromise里的状态将改变,也将遍历执行第二个myPromise作用域中的resolveList与rejectList里的函数,从而执行第二个then里的代码片段,以此类推,有无数个then的情况,代码如下:
// 三个状态
const PENDING = 'PENDING' // 默认状态
const FULFILLED = 'FULFILLED' // 成功
const REJECT = 'REJECT' // 失败
class myPromise{
constructor(exector) { // exector执行器,是一个方法,默认立即执行
this.state = PENDING
this.successData = undefined // 保存成功的信息
this.errorData = undefined // 保存失败的信息
this.resolveList = []
this.rejectList = []
// 改变状态
const resolve = (value) => {
if (this.state === PENDING)
this.successData = value
this.state = FULFILLED
this.resolveList.forEach(fn => fn())
}
const reject = (error) => {
this.errorData = error
this.state = REJECT
this.rejectList.forEach(fn => fn())
}
exector(resolve, reject) // 执行器有两个参数,resolve,reject
}
then(resolveFn, rejectFn) {
let promise2 = new myPromise((resolve, reject) => { // 立即执行
// 获取到数据,成功的数据,还是失败的数据
if (this.state === FULFILLED) {
let x = resolveFn(this.successData)
resolve(x)
}
if (this.state === REJECT) {
let x = rejectFn(this.errorData)
reject(x)
}
if (this.state === PENDING) {
this.resolveList.push(() => {
let x = resolveFn(this.successData)
resolve(x)
})
this.rejectList.push(() => {
let x = rejectFn(this.errorData)
reject(x)
})
}
})
return promise2
}
}
下面代码将输出 OK 100
const promise = new myPromise((resolve,reject) => {
setTimeout(() => {
resolve('OK')
}, 1000)
}).then((data) => {
console.log(data)
return 100
}).then((data) => {
console.log(data)
})
- 2、then返回的是一个promise,比如下列代码:
const promise = new myPromise((resolve,reject) => {
setTimeout(() => {
resolve('OK')
}, 1000)
}).then((data) => {
console.log(data)
return new myPromise((resolve,reject)=> {
resolve(100)
})
}).then((data) => {
console.log(data)
})
源码then方法就有问题,必须判断返回类型,如果then里面的回调函数返回类型是promise,则执行回调函数返回的promise执行成功或者失败后,执行then里面定义的promise的作用域下的resolve,reject方法,代码如下:
// 三个状态
const PENDING = 'PENDING' // 默认状态
const FULFILLED = 'FULFILLED' // 成功
const REJECT = 'REJECT' // 失败
// 判断then里面的返回值是否是promise,还是普通值,并执行不同的操作
function resolvePromise(x, promise2,resolve,reject) {
// 1普通值 2 promise
// 1 处理 返回值, x 如果等于promise2,提示错误
if (x === promise2) {
return reject(new TypeError('同一个promise'))
}
// 判断x是普通值,还是promise
if (typeof x === 'object' && x !== null) {
// 执行成功回调和失败的回调有错误,有错误执行下一个
try {
let then = x.then
if (typeof then === 'function') {
then.call(x, (r) => {
resolve(r)
}, (j) => {
reject(j)
})
} else {
resolve(x)
}
} catch(e) {
reject(e)
}
} else {
resolve(x)
}
}
class myPromise{
constructor(exector) { // exector执行器,是一个方法,默认立即执行
this.state = PENDING
this.successData = undefined // 保存成功的信息
this.errorData = undefined // 保存失败的信息
this.resolveList = []
this.rejectList = []
// 改变状态
const resolve = (value) => {
if (this.state === PENDING)
this.successData = value
this.state = FULFILLED
this.resolveList.forEach(fn => fn())
}
const reject = (error) => {
this.errorData = error
this.state = REJECT
this.rejectList.forEach(fn => fn())
}
exector(resolve, reject) // 执行器有两个参数,resolve,reject
}
then(resolveFn, rejectFn) {
let promise2 = new myPromise((resolve, reject) => { // 立即执行
// 获取到数据,成功的数据,还是失败的数据
if (this.state === FULFILLED) {
try{
let x = resolveFn(this.successData)
resolvePromise(x, promise2, resolve, reject)
} catch(e) {
reject(e)
}
}
if (this.state === REJECT) {
try{
let x = rejectFn(this.errorData)
resolvePromise(x, promise2, resolve, reject)
} catch(e) {
reject(e)
}
}
if (this.state === PENDING) {
this.resolveList.push(() => {
try{
let x = resolveFn(this.successData)
resolvePromise(x, promise2, resolve, reject)
} catch(e) {
reject(e)
}
})
this.rejectList.push(() => {
try{
let x = rejectFn(this.errorData)
resolvePromise(x, promise2, resolve, reject)
} catch(e) {
reject(e)
}
})
}
})
return promise2
}
}