- Promise就是一个类 在执行这个类的时候需要传递一个执行器进去,执行器会立即执行
- Promise中有三种状态:成功(fulfilled)、失败(rejected)和等待(pending),一旦状态确定就不能改,状态只能从等待变为成功或者变为失败
- resolve和reject函数是用来更改状态的
- then方法内部做的事情就是判断状态,如果状态是成功 调用成功的回调函数。then方法是被定义在原型对象中的
- then成功回调有一个参数 表示成功之后的值,失败回调参数表示失败的原因
- then方法可以被多次调用
- then方法是可以被链式调用的,后面then方法的回调函数拿到的值是上一个then方法的回调函数的返回值
- then方法的参数是可选参数
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
// 成功回调
successCallback = []
// 失败回调
failCallback = []
resolve = value => {
// 如果状态不是等待 阻止程序向下执行
if(this.status !== PENDING) return
this.status = FULFILLED
this.value = value
// 判断成功回调是否存在 如果存在就调用
while(this.successCallback.length){
this.successCallback.shift()()
}
}
reject = reason => {
// 如果状态不是等待 阻止程序向下执行
if(this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
// 判断失败回调是否存在 如果存在就调用
while(this.failCallback.length){
this.failCallback.shift()()
}
}
then (successCallback, failCallback) {
// 如果不传参数或者传递的不是函数 那就补充一个函数
if(Object.prototype.toString.call(successCallback) !== "[object Function]"){
successCallback = value => value
}
if(Object.prototype.toString.call(failCallback) !== "[object Function]"){
failCallback = reason => { throw reason }
}
let promise2 = new MyPromise((resolve,reject) => {
if(this.status === FULFILLED) {
queueMicrotask(()=> {
try{
// 上一个then的成功回调返回值
let x = successCallback(this.value)
// 判断 x 的值是普通值还是promise对象
// 如果是普通值,直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promise2,x,resolve,reject)
}catch (e) {
reject(e)
}
})
} else if(this.status === REJECTED) {
queueMicrotask(()=> {
try{
// 上一个then的成功回调返回值
let x = failCallback(this.reason)
// 判断 x 的值是普通值还是promise对象
// 如果是普通值,直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promise2,x,resolve,reject)
}catch (e) {
reject(e)
}
})
} else {
// 等待
// 将成功回调和失败回调存储起来
this.successCallback.push(()=> {
queueMicrotask(()=> {
try{
// 上一个then的成功回调返回值
let x = successCallback(this.value)
// 判断 x 的值是普通值还是promise对象
// 如果是普通值,直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promise2,x,resolve,reject)
}catch (e) {
reject(e)
}
})
})
this.failCallback.push(() => {
queueMicrotask(()=> {
try{
// 上一个then的成功回调返回值
let x = failCallback(this.reason)
// 判断 x 的值是普通值还是promise对象
// 如果是普通值,直接调用resolve
// 如果是promise对象 查看promise对象返回的结果
// 再根据promise对象返回的结果 决定调用resolve 还是调用reject
resolvePromise(promise2,x,resolve,reject)
}catch (e) {
reject(e)
}
})
})
}
})
return promise2
}
}
function resolvePromise(promise2, x, resolve, reject){
if(promise2 === x) {
return reject(new TypeError(""))
}
if(x instanceof MyPromise) {
// promise对象
x.then(resolve, reject)
} else {
// 普通值
resolve(x)
}
}
- 如果promise.then返回的是它本身返回的promise,就会出现循环调用promise的错误
var promise = new Promise((resolve, reject) => {
resolve(100)
})
var p1 = promise.then(val => {
console.log(val)
return p1 // 会出现循环调用的情况
})
p1.then(() => {}, err => {
console.log(err) // 系统的promise能识别循环调用的错误
})
- Promise.all方法实现
- 接受一个数组,会按照数组中元素的顺序调用异步代码执行,得到的结果就是调用的顺序
- 返回一个promise,支持链式调用
- 数组中所有promise都是成功的,才会变为成功状态,只要有一个失败 就会变为失败状态
class MyPromise() {
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) {
resolve(result)
}
}
for(let i = 0; i < array.length; i++) {
let current = array[i];
if(current instanceof MyPromise) {
// promise对象
current.then(value => addData(i, value), error => reject(error))
}else {
// 普通值
addData(i, array[i])
}
}
})
}
}
- Promise.resolve方法实现
class MyPromise {
static resolve (value) {
if(value instanceof MyPromise) {
// 参数是promise
return value
} else {
// 不是promise
return new MyPromise(resolve => resolve(value))
}
}
}
- finally方法
不管成功还是失败都会执行
class MyPromise {
finally(callback) {
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, error => {
return MyPromise.resolve(callback()).then(() => error)
})
}
}
- catch方法
class MyPromise {
catch(failCallback) {
return this.then(undefined, failCallback)
}
}