整体思路:
- 1.通过new Promise(),得知Promise是一个类
- 2.创建Promise需要一个执行方法,并且在构造时,立即调用该执行器
- 3.promise有三种状态:等待(pending)、成功(fulfilled)、失败(rejected)
- 但只有两条路线可选,要么成功,要么失败,一旦确定状态,便不可更改
- 等待(pending)-> 成功(fulfilled)
- 等待(pending)-> 失败(rejected)
- 但只有两条路线可选,要么成功,要么失败,一旦确定状态,便不可更改
- 4.resolve 和 reject 用来更改状态的,需要在构造Promise时传递给调用者使用
- resolve : fulfilled
- reject: rejected
- 5.then 分别处理 成功状态 和 失败状态 下的回调方法方法。并需要传递对应的值。且该方法是定义在原型对象中的
- 6.异步执行resolve和reject时,Promise中拿到的状态是pending值,所以无法去调用resolve 或 reject方法
- 7.Promise可以多次调用then()方法,同时需返回多次结果
- 8.Promise具有链式调用的情况,链式调用拿到的都是全新的Promise对象
- 9.链式调用中,识别到调用到了promise自己本身时,需报错
- 10.捕获执行器、链式调用中的异常情况
- 11.then()方法的参数是可选的:如果then()方法里没有参数,其运行方式应该是把上一次的返回的结果,传递给下一个then()
相关的方法实现:
-
- Promise.all([])
- all()方法是静态的
- all(array)方法传递的是数组,数组中可以是普通值,也可以是Promise对象
- 整个方法按照数组的顺序执行,数组中有异步操作,需等待异步操作执行完后,才能结束方法
- all(array)方法返回的也是Promise对象
- all(array)方法的数组参数中,有一个失败,则整体都失败
-
- Promise.resolve()
- 该方法是静态的
- 若传入的参数是Promise对象,则返回该对象
- 若传入的参数是普通值,则新建Promise对象,再返回
-
- finally()
- 该方法是Promise原型上的
- 无论上一步操作是否成功,都会执行该方法
- finally()返回的是Promise对象
- finally()里的方法有异步操作时,等待该操作结束
-
- catch()
- 该方法是Promise原型上的
- catch()返回的是Promise对象
- 为了捕获异常
创建
(MyPromise.js)
//状态常量(可提示、可重用)
const PENDING = "pending" //等待
const FULFULLED = "fulfilled" //成功
const REJECTED = "rejected" //失败
//promise是个类
class MyPromise {
//状态,默认为等待
status = PENDING
//成功状态下的值
value = undefined
//失败状态下的原因
reason = undefined
//成功回调需要用数组将回调函数组装起来
successCallback = []
//失败回调需要用数组将回调函数组装起来
failCallback = []
//创建promise时,需要一个执行器executor,该执行器需要将resolve和reject方法传递过去,供调用者使用。并立即调用该执行器
constructor(executor) {
//捕获执行器中的异常,并给到reject中
try {
executor(this.resolve, this.reject)
} catch (err) {
this.reject(err)
}
}
//修改状态为 成功
resolve = (value) => {//使用箭头函数是为了将this指向Promise
//判断状态是否已改变。若已改变,则不能修改
if (this.status !== PENDING) return;
this.status = FULFULLED
this.value = value
//循环执行成功回调数组里的函数
while (this.successCallback.length) {
//shift()方法:删除数组中的第一个值,并返回该值
this.successCallback.shift()(this.value)
}
}
//修改状态为 失败
reject = (reason) => {
//判断状态是否已改变。若已改变,则不能修改
if (this.status !== PENDING) return;
this.status = REJECTED
this.reason = reason
//循环执行失败回调数组里的函数
while (this.failCallback.length) {
//shift()方法:删除数组中的第一个值,并返回该值
this.failCallback.shift()(this.reason)
}
}
//调用Promise处理结果
then(successCallback, failCallback) {
//判断then()方法中是否有参数
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
// 链式调用时,then()方法返回的是全新的promise对象
// 在这里需要创建一个新的promise对象
let newPromise = new MyPromise((resolve, reject) => {
//判断状态
if (this.status === FULFULLED) {//状态为成功
//按照javascript的代码执行流程,此处是获取不到newPromise对象,需要将整个代码块进行异步操作处理
setTimeout(() => {
//在then()方法的resolve函数中发生异常,需要在调用resolve函数时捕获异常
try {
//then()里的有返回值时,此处是可以接受到的
//并且反馈给新的promise对象中的resolve
let retValue = successCallback(this.value)
//判断返回值是否为当前对象或promise实例
resolvePromise(newPromise, retValue, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
} else if (this.status === REJECTED) {//状态为失败
setTimeout(() => {
try {
let retValue = failCallback(this.reason)
resolvePromise(newPromise, retValue, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
} else {//针对异步情况下,其状态为等待,需对其回调方法做保存
this.successCallback.push(() => {
setTimeout(() => {
//在异步操作情况下,处理异常情况
try {
let retValue = successCallback(this.value)
resolvePromise(newPromise, retValue, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
let retValue = failCallback(this.reason)
resolvePromise(newPromise, retValue, resolve, reject)
} catch (err) {
reject(err)
}
}, 0)
})
}
})
return newPromise
}
/**
* 该方法是Promise原型上的
* 无论上一步操作是否成功,都会执行该方法
* finally()返回的是Promise对象
* finally()里的方法有异步操作时,等待该操作结束
*/
finally(callback) {
//判断上一步操作是否成功,可以使用then()
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => { throw reason })
})
}
/**
* 该方法是Promise原型上的
* catch()返回的是Promise对象
* 为了捕获异常
*/
catch(failCallback) {
return this.then(undefined, failCallback)
}
/**
* all()方法是静态的
* all(array)方法传递的是数组,数组中可以是普通值,也可以是Promise对象
* 整个方法按照数组的顺序执行,数组中有异步操作,需等待异步操作执行完后,才能结束方法
* all(array)方法返回的也是Promise对象
* all(array)方法的数组参数中,有一个失败,则整体都失败
*/
static all(array) {
let result = []
let index = 0//已执行个数。为等待异步操作结束
return new MyPromise((resolve, reject) => {
for (let i = 0; i < array.length; i++) {
let current = array[i]
/**将值放入result中 */
function addValue(idx, value) {
index++
result[idx] = value
//如果 result数组中的数量 不等于 参数数组中的数量,继续等待异步操作执行
if (index === array.length) {
resolve(result)
}
}
//判断数组成员的类型
if (current instanceof MyPromise) {//MyPromise实例
//Promise对象,需要执行该Promise对象,然后将值放入result中
current.then(value => {
//执行成功,将返回结果放入result中
addValue(i, value)
}, reason => {
//执行失败,结束当前promise,并返回失败信息
reject(reason)
})
} else {//普通值
addValue(i, current)
}
}
})
}
/**将参数快速组成Promise对象,然后返回
* 该方法是静态的
* 若传入的参数是Promise对象,则返回该对象
* 若传入的参数是普通值,则新建Promise对象,再返回
*/
static resolve(value) {
//判断是否是Promise对象
if (value instanceof MyPromise) return value;
return new MyPromise((resolve, reject) => resolve(value))
}
}
/**解析值的状态,并调用不同的方法 */
function resolvePromise(currPromise, value, resolve, reject) {
if (value instanceof MyPromise) {//promise实例
//根据该promise实例的不同结果状态,调用不同方法
if (currPromise === value) {
return reject(new TypeError("循环调用,报错,报错,报错!"))
}
value.then(resolve, reject)
} else {//普通值
resolve(value)
}
}
//node环境下使用module.exports将对象抛出去
module.exports = MyPromise