promise的实现思路
-
promise是一个类,传入一个函数,函数会立即执行。有两个固定参数resolve和reject
-
promise执行的时候有三种状态 进行中 pending 成功 fulfilled 失败 rejected。 状态变更只有以下两种,且是不可逆的 ① pending => fulfilled ② pending => rejected
-
resolve是用来把状态更改为成功的函数。 reject是用来把状态更改为失败的函数
-
then方法是根据状态,来执行成功和失败回调函数
-
成功的回调函数能接收到状态变更时传递的值 失败的回调函数能接收到状态变更为失败时传递的值
-
在状态还是pending的情况下,即进行异步操作的时候,要把成功和失败的回调函数存储起来,然后在状态变更时,依次执行回调
-
实现链式调用then方法,即在调用then方法的时候,要返回一个promise对象。上一个then方法的返回值,是下一个then的value
-
链式调用then方法的参数可以不传,变为可选参数。一直把第一个的返回值,原封不动的返回给下一个then
-
finally方法,传递一个函数,返回一个promise对象和上一个promise返回的值(如果有的话)
-
promise.resolve方法,作用是将现有对象转为 Promise 对象。传递一个参数,返回一个promise对象
-
promise.all方法 传递一个数组,按照数组里面的顺序,处理完后,按照顺序返回结果。如果是普通值,则直接返回,如果是promise,则处理后返回。需要等数组里的元素全部变成resolve时返回,如果有一个状态为reject,则直接返回reject
-
promise.race方法 传递一个数组,如果是普通值,则变成promise返回,如果是promise,则处理后返回。只要有一个的状态变了,就返回那个
-
promise.first方法,将多个 Promise 实例,包装成一个新的 Promise 实例,只要参数实例有一个变成 fulfilled 状态,包装实例就会变成 fulfilled 状态;如果所有参数实例都变成 rejected 状态,包装实例就会变成 rejected 状态。
-
promise.last方法,将多个 Promise 实例,包装成一个新的 Promise 实例,获取最后一个 promise 实例的状态,并将其作为包装实例的状态返回
-
promise.none方法,将多个 Promise 实例,包装成一个新的 Promise 实例,获取第一个状态为 fulfilled 状态的实例,将其作为包装实例的 rejected 状态返回, 如果所有实例状态都为 rejected ,则返回一个数组,将其作为包装实例的 fulfilled 状态返回
const PENDING = 'pending' // 等待中
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败
class myPromise {
constructor(init) {
try { // 捕获初始化发生错误的时候
init(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
}
// promise 状态
status = PENDING
// 状态变更为成功时传递的值
resolveData = undefined
// 状态变更为失败时,传递的错误日志
error = undefined
// 成功回调函数,异步情况下会有多个
successCallback = []
// 失败回调函数,异步情况下会有多个
failCallback = []
//resolve和reject写成箭头函数的原因是:让this指向myPromise。因为在new myPromise的时候是直接执行了这两个函数,会导致它的this指向window,所以这里得改变一下指向
resolve = resolveData => {
// 如果状态不是等待,停止执行
if(this.status !== PENDING) return
// 更改状态为成功
this.status = FULFILLED
// 接收成功后返回的值
this.resolveData = resolveData
// 异步情况时,如果存在就,执行成功回调函数
while(this.successCallback.length) { // 依次执行数组里面所有的回调
// this.successCallback.shift()(this.resolveData) // 这个写法是不接收then的返回值的写法
this.successCallback.shift()() // 这个写法是接收then的返回值的写法
}
}
reject = error => {
// 如果状态不是等待,停止执行
if(this.status !== PENDING) return
// 更改状态为失败
this.status = REJECTED
// 接收失败后返回的值
this.error = error
// 异步情况时,如果存在就,执行失败回调函数
while(this.failCallback.length) { // 依次执行数组里面所有的回调
// this.failCallback.shift()(this.error) // 这个写法是不接收then的返回值的写法
this.failCallback.shift()() // 这个写法是接收then的返回值的写法
}
}
// 这里不用箭头函数的原因是:then方法是new myPromise直接调用的,所以this本来就指向myPromise
then(successCallback, failCallback) {
// then方法的参数可以不传,变为可选参数
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : err => { throw err }
let promise2 = new myPromise((resolve, reject)=>{ //实现链式调用
if(this.status === FULFILLED) { // 执行成功的回调
setTimeout(() => { // promise2 是自己本身,但是由于这里是同步执行的,拿不到promise2这个变量,因为还没执行完,所以把这部分变为异步的
try {
// 接收上一个then方法的返回值,作为下次then的value
let result = successCallback(this.resolveData)
//判断返回的结果
this.handleReturnThen(promise2, result, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
}else if(this.status === REJECTED) { // 执行失败的回调
setTimeout(() => { // promise2 是自己本身,但是由于这里是同步执行的,拿不到promise2这个变量,因为还没执行完,所以把这部分变为异步的
try {
// 接收上一个then方法的返回值,作为下次then的value
let result = failCallback(this.error)
//判断返回的结果
this.handleReturnThen(promise2, result, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
}else {
// 等待。把成功和失败的回调函数存起来, 因为promise可以多次调用,所以回调函数会有多个。而同步情况下会一个个执行,所以不用处理,异步情况下就要把回调函数都存起来
// 下面这个写法是不接收then的返回值的写法
// this.successCallback.push(successCallback)
// this.failCallback.push(failCallback)
// 下面这个写法是要接收then的返回值的写法
this.successCallback.push(()=>{
setTimeout(() => { // promise2 是自己本身,但是由于这里是同步执行的,拿不到promise2这个变量,因为还没执行完,所以把这部分变为异步的
try {
// 接收上一个then方法的返回值,作为下次then的value
let result = successCallback(this.resolveData)
//判断返回的结果
this.handleReturnThen(promise2, result, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
})
this.failCallback.push(()=>{
setTimeout(() => { // promise2 是自己本身,但是由于这里是同步执行的,拿不到promise2这个变量,因为还没执行完,所以把这部分变为异步的
try {
// 接收上一个then方法的返回值,作为下次then的value
let result = failCallback(this.error)
//判断返回的结果
this.handleReturnThen(promise2, result, resolve, reject)
} catch (error) {
reject(error)
}
}, 0);
})
}
})
return promise2
}
catch(failCallback) {
return this.then(undefined, failCallback)
}
finally (callback) { // 不管是请求成功还是失败都会执行
return this.then(
// 这里是处理传递的参数后,返回一个promise对象,并把上一个返回值原样返回给下一个
value => myPromise.resolve(callback()).then(() => value),
error => myPromise.resolve(callback()).then(() => { throw error })
)
}
static resolve (data) {
// 如果没有参数,默认返回undefined
data = data ? data : undefined
// 如果参数是promise对象则直接返回,如果是普通值则经过处理后返回一个promise
if(data instanceof myPromise) return data
return new myPromise((resolve) => {
resolve(data)
})
}
static all (array) {
// 要返回的数组
let result = []
// 用来处理异步情况的中间值
let index = 0
return new myPromise((resolve, reject) => {
// 往数组按原来的顺序添加返回结果
function addData(key, value) {
result[key] = value
index++
if(index == array.length) {//判断promise是否全部执行完,因为只有异步操作执行完了,才会执行addData,然后再执行resolve
resolve(result)
}
}
for (let key in array) {
if (array[key] instanceof myPromise) { //如果数组里的元素是promise对象,则处理后返回
array[key].then(
value => addData(key, value),
error => reject(error)
)
}else { // 直接返回
addData(key, array[key])
}
}
})
}
static race(array) {
return new myPromise((resolve, reject) => {
for (let key in array) {
if (array[key] instanceof myPromise) { //如果数组里的元素是promise对象,则处理后返回
array[key].then(
value => resolve(value),
error => reject(error)
)
}else { // 直接返回
resolve(array[key])
}
}
})
}
static first(promiseList) => {
return new myPromise((resolve, reject) => {
let num = 0
const len = promiseList.length
promiseList.forEach((pms) => {
myPromise.resolve(pms)
.then(resolve)
.catch(() => {
num++
if (num === len) {
reject('AggregateError: All promises were rejected')
}
})
})
})
}
static last(promiseList) => {
return new myPromise((resolve, reject) => {
let num = 0
const len = promiseList.length
const fn = (res, bol) => {
if (++num === len) {
bol ? resolve(res) : reject(res)
}
}
promiseList.forEach((pms) => {
myPromise.resolve(pms)
.then((res) => {
fn(res, true)
})
.catch((err) => {
fn(err, false)
})
})
})
}
static none(promiseList) => {
return myPromise.all(
promiseList.map((pms) => {
return new myPromise((resolve, reject) => {
// 将pms的resolve和reject反过来
return myPromise.resolve(pms).then(reject, resolve)
})
})
)
}
handleReturnThen = (promise, result, resolve, reject) => {
// 判断返回值是普通值,还是promise对象
// 如果是普通值,则直接返回
// 如果是promise(不能返回自己本身),则运行,并返回对应的结果。
if(promise === result) {
return reject(new TypeError('不能返回自己本身'))
}
if(result instanceof myPromise) {
result.then(resolve, reject)
}else {
resolve(result)
}
}
}