一、首先要了解这几个关键问题:
1.如何改变Promise状态?
resolve(value);如果当前是pending就会变为resolved;
rejected(reason);如果当前是pending就会变为rejected;
抛出异常;如果当前是pending就会变为rejected;
2.一个promise指定多少个成功/失败的回调都会调用吗?
当promise改变对应的状态时会调用;
3.改变Promise状态和指定回调函数谁先谁后?
(1)都有可能,正常情况下是先指定回调再改变状态;但也可以先改变状态再指定回调;
(2)如何先该状态再指定回调?
在执行器中直接调用resolve()/rejected()延长更长的时间才调用then()
(3) 什么时候才能得到数据?
先制定的回调,那当状态发生改变时,回调函数就会调用,得到数据;
如果先改变状态,那指定回调函数时,回调函数就会调用,得到数据;
4.Promise.then()返回的新promise()的状态由什么决定?
简洁来说:由then()指定的回调函数的结果来执行
详细来说: 1、如果抛出异常,新promise变为rejected 状态,err变为抛出的异常;
2、如果抛出非promise的任意值,新promise变为resolve状态, res为返回的值;包括(undefined\、null)
3、如果抛出新的promise, 此的promise返回的结果就是新promise的状态;
5.Promise如何串联多个操作任务?
(1)通过promise的then()返回一个新的Promise,可以看成then()的链式调用;
(2)通过then的链式调用串联都多个同步/异步任务
6.Promise异常穿透?
(1)当使用Promise.then()链式调用时,可以在最后指定失败的回调;
(2)前面任何操作出了异常,都会传到最后的失败的回调函数处理;
7.中断Promise链?
(1)使用Promise.then链式调用时,在中间中断,不再调用后面的回调函数;
(2)在回调函数中返回一个pending状态的Promise
二、了解这个几个问题之后我们再来手写实现思路会很清晰:
//匿名函数自调用表达式
(function (window) {
//Promise 构造函数
//excutor 执行器函数(同步)
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
function Promise(excutor) {
const _this = this
_this.status = PENDING //给Promise指定status属性,用于存储Promise当前的状态,初始值为PENDING
_this.data = undefined //给Promise指定data属性,用于存储结果数据
_this.callbacks = [] //给Promise指定callbacks属性,用于存储指定的回调函数{onRESOLVED () {}, onRejected () {}}
function resolve (value) {
console.log('this', this)
//如果当前状态不是PENDING,直接返回
if (_this.status !== PENDING) {
return
}
//状态改为resolced
_this.status = RESOLVED
//保存value数据
_this.data = value
//如果有待执行的回调函数,立即异步调用指定的回调函数
if (_this.callbacks.length > 0) {
setTimeout(() => { //放入队列中执行待成功的回调
_this.callbacks.forEach(callbackObj => {
callbackObj.onResolved(value)
});
}
})
}
function reject (reason) {
//如果当前状态不是PENDING,直接返回
if (_this.status !== PENDING) {
return
}
//状态改为rejected
_this.status = REJECTED
//保存reason数据
_this.data = reason
//如果有待执行的回调函数,立即异步调用指定的回调函数
if (_this.callbacks.length > 0) {
setTimeout(() => { //放入队列中执行待成功的回调
_this.callbacks.forEach(callbackObj => {
callbackObj.onRejected(reason)
});
}
})
}
try {
excutor(resolve, reject)
} catch (error) { //如果执行器捕获到异常,promise对象变为rejected状态
reject(error)
}
}
//then原型对象的方法
//指定一个成功和者失败的回调,返回一个promise
Promise.prototype.then = function (onResolved, onRejected) {
//指定默认的回调
onResolved === 'function' ? onResolved : value => value
//错误穿透关键一步
onResolved === 'function' ? onRejected : resaon => {throw reason}
const _this = this
// 调用指定的回调函数,根据回调函数指定的结果, 改变return的promise状态
/**
* 返回的promise的状态由onResolved/onRejected执行返回的promise的结果来决定:
* 1.如果抛出异常,返回的promise为rejected状态;
* 2.如果返回的是非promise的任意值,返回的promise为resolved状态;
* 3.如果返回的是promise,return的promise的结果就是这个promise的结果;
*/
const handel = function (callback) {
try {
const result = callback(_this.data)
if (result instanceof Promise) {
//3.如果回调函数返回的时promise,return的promise的结果就是这个promise的结果
setTimeout(() => {
result.then(resolve, reject)
})
} else {
//2.如果回调函数返回的不是promise,return的promise就会成功,value就是返回的值
resolve(result)
}
} catch (error) {
//1.如果抛出异常,return的promise就会失败,reason就是error
reject(error)
}
}
return new Promise((resolve, reject) => {
//pending状态,将异步回调函数保存起来
if (_this.status === PENDING) {
_this.callbacks.push({
onResolved (value) {
handel(onResolve)
},
onRejected (reason) {
handel(onReject)
}
})
} else if (_this.status === RESOLVED) {
//resolved状态,异步执行onResolved(){}并改变return的promise的状态
handel(onResolved)
} else {
//rejected状态,异步执行onRejected(){}并改变return的promise的状态
handel(onRejected)
}
})
}
//catch原型对象的方法
Promise.prototype.catch = function (onRejected) {
return this.then(undefined, onRejected)
}
//resolve函数对象的方法
//返回一个成功或失败的promise
Promise.resolve = function (value) {
//返回一个成功或失败的promise
return new Promise((resolve, reject) => {
//value是一个promise,使用value的结果作为promise的结果
if (value instanceof Promise) {
value.then(resolve, reject)
} else {//value不是promise,返回一个成功的promise
resolve(value)
}
})
}
//reject函数对象的方法
//返回一个指定结果的失败的promise
Promise.reject = function (reason) {
// 返回一个失败的promise
return new Promise((resolve, reject) => {
reject(reason)
})
}
//all函数对象的方法
//返回一个promise,只有当所有的promise都成功时才返回成功,否则只要有一个失败就失败
Promise.all = function (promises) {
const values = new Array(promises.length)
const promiseCount = 0
return new Promise((resolve, rejevt) => {
promises.forEach((promise, index) => {
Promise.resolve(promise).then(
value => {
promiseCount++ //成功就+1
values[index] = value //将成功的promise放入指定的位置
if (promiseCount == promises.length) {
resolve(values) //都成功则成功
}
},
reason => {//只要有一个失败就失败
reject(reason)
}
)
})
})
}
//race函数对象的方法
//返回一个promise,根据第一个改变状态的结果来决定成功还是失败
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
Promise.resolve(promises).forEach(promise => {
promise.then(
value => {
resolve(value)
},
reason => {
reject(reason)
}
)
})
})
}
window.Promise = Promise
})(window)