文章内容输出来源:拉勾教育大前端高薪训练营
文章说明:文章内容为学习笔记,学徒之心,仅为分享; 如若有误,请在评论区指出,如若您觉得文章内容对您有一点点帮助,请点赞、关注、评论,共享
上一篇:JavaScript 深度剖析
简单理解 Promise 的实现原理+自己手写一个 Promise
面试中,经常会被问到的问题:能否自己手动写一个 Promise,或者 Promise 内部是如何实现异步调用的?
1、你是否马上想到,完了不会啊 o(╥﹏╥)o,直接用,还不一定用的明白呢,内部代码如何实现的,鬼知道哇?
2、或者你也会想,管它内部怎么实现的,拿来直接用不就完事了,又不影响自己的代码编程 →_→
可是面试官特别喜欢问这样的问题,你回答不上来,那么这次的面试基本也就没有希望了【体现面试官很牛的样子,实际上面试官也不一定会。。。】
但是下面的内容,可以让你成功实现一个自己手写的 Promise, 解决面试中的一问三不知的情况
进入正题
要使用 Promise,首先要创建一个 Promise 对象才行,
那么如何创建 Promise 对象?需要通过 new 关键字去执行 Promise 就可以了
new Promise((resolve,reject)=>{})
1、由上面的代码可以看出 Promise 是一个类,在执行这个类的时候,需要传递一个执行器函数进去,同时这个执行器函数是立即执行的
2、执行器函数里面的 2 个参数 resolve、reject 其实是 2 个函数,这 2 个函数的目的就是去更改 Promise 的状态
resolve:fulfilled 把状态更改为成功
reject: rejected 把状态更改为失败
3、在 Promise 中的状态有 3 种:
- pending 等待
- fulfilled 成功
- rejected 失败
Promise 中的状态只能是由等待状态 变成 成功状态 或者 由等待状态 变成 失败状态
pending --> fulfilled
pending --> rejected
一旦状态确定就不可更改
4、Promise 中的 then 方法内部做的事情就是判断 Promise 状态,如果 Promise 状态是成功,就调用 then()方法里面的成功的回调函数,也就是第一个函数,如果 Promise 状态是失败,就调用 then()方法里面的失败的回调函数,也就是第二个函数,then()方法石碑定义在原型对象中的
5、Promise 中的 then 方法内成功的回调函数有一个参数,表示成功之后的值,then 方法内失败的回调函数有一个参数,表示失败之后的值,
接下来按照上面的 5 点来创建最简单的 Promise 原理的代码
1、Promise 类核心逻辑实现
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
// 接收执行器,执行器是立即执行的
constructor(executor) {
// 执行器接收2个函数resolve,reject,这2个函数是用来更改promise的状态的
// 一旦promise状态确定就不可更改
executor(this.resolve, this.reject)
}
status = PENDING // promise的状态
value = undefined // 成功之后的值
reason = undefined // 失败之后的值
// 用箭头函数的原因是为了解决this的指向问题
// resolve函数是用来更改promise的状态的
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为成功
this.status = FULFILLED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.value = value
}
// resolve函数是用来更改promise的状态的
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为失败
this.status = REJECTED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.reason = reason
}
then(sucessCallback, failCallback) {
// 判断promise的状态
if (this.status === FULFILLED) {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
sucessCallback(this.value)
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
failCallback(this.reason)
}
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
let p1 = new MyPromise((resolve, reject) => {
resolve('成功')
// reject('失败')
})
p1.then(
value => {
console.log(value)
},
reason => {
console.log(reason)
}
)
这样最简单的 Promise 就创建完成了
2、在 Promise 类中加入异步逻辑
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING
value = undefined
reason = undefined
sucessCallback = undefined // then()方法里面的成功的回调
failCallback = undefined // then()方法里面的失败的回调
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
if (this.sucessCallback) {
this.sucessCallback(this.value)
}
}
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
if (this.failCallback) {
this.failCallback(this.reason)
}
}
then(sucessCallback, failCallback) {
if (this.status === FULFILLED) {
sucessCallback
sucessCallback(this.value)
} else if (this.status === REJECTED) {
failCallback
failCallback(this.reason)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为执行器是同时执行的,然后执行器在执行的时候,发现自身里面没有找到promise的状态,
// 这时在执行then()的时候,then()方法不知道应该调用成功的回调还是失败的回调
// 所以then()方法里面打印出来的是空
// then()方法不知道应该调用成功的回调还是失败的回调的时候,
// 先把sucessCallback, failCallback,给保存起来
// 2秒后,就可以确认调用resolve()还是reject()函数,
// 同时把值传递给then()方法里面的对应的成功的回调或者失败的回调
this.sucessCallback = sucessCallback
this.failCallback = failCallback
}
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
let p1 = new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为执行器是同时执行的,然后执行器在执行的时候,发现自身里面没有找到promise的状态,
// 这时在执行then()的时候,then()方法不知道应该调用成功的回调还是失败的回调
// 所以then()方法里面打印出来的是空
// 然后去MyPromise.js文件中处理异步请求的情况
setTimeout(() => {
resolve('成功')
// reject('失败')
}, 2000)
})
p1.then(
value => {
console.log(value)
},
reason => {
console.log(reason)
}
)
3、在 Promise 类中实现 then 方法的多次调用,添加多个处理函数
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING
value = undefined
reason = undefined
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()(this.value)
}
}
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()(this.reason)
}
}
then(sucessCallback, failCallback) {
if (this.status === FULFILLED) {
sucessCallback
sucessCallback(this.value)
} else if (this.status === REJECTED) {
failCallback
failCallback(this.reason)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
this.sucessCallback.push(sucessCallback)
this.failCallback.push(failCallback)
}
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
let p1 = new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
setTimeout(() => {
resolve('异步执行,成功')
// reject('异步执行,失败')
}, 2000)
// resolve('成功')
// reject('失败')
})
// then方法被调用了3次
p1.then(
value => {
console.log(value)
},
reason => {
console.log(reason)
}
)
p1.then(
value => {
console.log(value)
},
reason => {
console.log(reason)
}
)
p1.then(
value => {
console.log(value)
},
reason => {
console.log(reason)
}
)
4、在 Promise 类中实现 then 方法的链式调用一
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING
value = undefined
reason = undefined
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()(this.value)
}
}
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()(this.reason)
}
}
then(sucessCallback, failCallback) {
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
failCallback(this.reason)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
this.sucessCallback.push(sucessCallback)
this.failCallback.push(failCallback)
}
})
return promise2
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
let p1 = new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// setTimeout(() => {
// resolve('异步执行,成功')
// // reject('异步执行,失败')
// }, 2000)
resolve('成功')
// reject('失败')
})
// then方法的链式调用
// 后面then方法里面的回调函数拿到的值,是前一个then方法里面回调函数的返回值
// then方法是promise对象里的方法,想要实现then方法的链式调用,
// 需要每一个then方法都要返回promise对象才可以
p1.then(
value => {
console.log(value)
return 100
},
reason => {
console.log(reason)
}
).then(
value => {
console.log(value) // 100
},
reason => {
console.log(reason)
}
)
5、在 Promise 类中实现 then 方法的链式调用二
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING
value = undefined
reason = undefined
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()(this.value)
}
}
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()(this.reason)
}
}
then(sucessCallback, failCallback) {
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
failCallback(this.reason)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
this.sucessCallback.push(sucessCallback)
this.failCallback.push(failCallback)
}
})
return promise2
}
}
// x 是前一个then方法里面的回调的返回值
function resolvePromise(x, resolve2, reject2) {
if (x instanceof MyPromise) {
// x 是promise对象
// x.then((value) => resolve2(value), (reason) => reject2(reason))
x.then(resolve2, reject2)
} else {
// x 是普通值
resolve2(x)
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
let p1 = new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// setTimeout(() => {
// resolve('异步执行,成功')
// // reject('异步执行,失败')
// }, 2000)
resolve('成功')
// reject('失败')
})
function other() {
return new MyPromise((resolve, reject) => {
return resolve('other')
})
}
// then方法的链式调用
// 后面then方法里面的回调函数拿到的值,是前一个then方法里面回调函数的返回值
// then方法是promise对象里的方法,想要实现then方法的链式调用,
// 需要每一个then方法都要返回promise对象才可以
p1.then(
value => {
console.log(value)
return other()
},
reason => {
console.log(reason)
// return other()
}
).then(
value => {
console.log(value) // other
},
reason => {
console.log(reason)
}
)
6、then 方法链式调用识别 Promise 对象自返回
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
constructor(executor) {
executor(this.resolve, this.reject)
}
status = PENDING
value = undefined
reason = undefined
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = FULFILLED
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()(this.value)
}
}
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
this.status = REJECTED
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()(this.reason)
}
}
then(sucessCallback, failCallback) {
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
failCallback(this.reason)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
this.sucessCallback.push(sucessCallback)
this.failCallback.push(failCallback)
}
})
return promise2
}
}
// x 是前一个then方法里面的回调的返回值
function resolvePromise(x, resolve2, reject2) {
if (x instanceof MyPromise) {
// x 是promise对象
// x.then((value) => resolve2(value), (reason) => reject2(reason))
x.then(resolve2, reject2)
} else {
// x 是普通值
resolve2(x)
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
let p1 = new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// setTimeout(() => {
// resolve('异步执行,成功')
// // reject('异步执行,失败')
// }, 2000)
resolve('成功')
// reject('失败')
})
function other() {
return new MyPromise((resolve, reject) => {
return resolve('other')
})
}
// then方法的链式调用
// 后面then方法里面的回调函数拿到的值,是前一个then方法里面回调函数的返回值
// then方法是promise对象里的方法,想要实现then方法的链式调用,
// 需要每一个then方法都要返回promise对象才可以
p1.then(
value => {
console.log(value)
return other()
},
reason => {
console.log(reason)
// return other()
}
).then(
value => {
console.log(value) // other
},
reason => {
console.log(reason)
}
)
7、捕获错误及 then 链式调用其他状态代码补充
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
// 接收执行器,执行器是立即执行的
constructor(executor) {
// 执行器接收2个函数resolve,reject,这2个函数是用来更改promise的状态的
// 一旦promise状态确定就不可更改
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
// executor(this.resolve, this.reject)
}
status = PENDING // promise的状态
value = undefined // 成功之后的值
reason = undefined // 失败之后的值
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
// 用箭头函数的原因是为了解决this的指向问题
// resolve函数是用来更改promise的状态的
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为成功
this.status = FULFILLED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()()
}
}
// resolve函数是用来更改promise的状态的
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为失败
this.status = REJECTED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()()
}
}
then(sucessCallback, failCallback) {
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// failCallback(this.reason)
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
// this.sucessCallback.push(sucessCallback)
// this.failCallback.push(failCallback)
this.sucessCallback.push(() => {
// sucessCallback()
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
this.failCallback.push(() => {
// failCallback()
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
}
})
return promise2
}
}
// x 是前一个then方法里面的回调的返回值
function resolvePromise(promise2, x, resolve2, reject2) {
if (promise2 === x) {
return reject2(
new TypeError('Chaining cycle detected for promise #')
)
}
if (x instanceof MyPromise) {
// x 是promise对象
// x.then((value) => resolve2(value), (reason) => reject2(reason))
x.then(resolve2, reject2)
} else {
// x 是普通值
resolve2(x)
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
let p1 = new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
setTimeout(() => {
resolve('异步执行,成功')
// reject('异步执行,失败')
}, 2000)
// resolve('成功')
// throw new Error('执行器错误')
// reject('失败')
})
function other() {
return new MyPromise((resolve, reject) => {
return resolve('other')
})
}
// then方法的链式调用
// 后面then方法里面的回调函数拿到的值,是前一个then方法里面回调函数的返回值
// then方法是promise对象里的方法,想要实现then方法的链式调用,
// 需要每一个then方法都要返回promise对象才可以
p1.then(
value => {
console.log(value)
// throw new Error('第一个then抛出错误')
},
reason => {
console.log(reason)
// return 10000
}
).then(
value => {
console.log(value)
},
reason => {
console.log(reason)
// return other()
}
)
8、将 then 方法的参数变成可选参数
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
// 接收执行器,执行器是立即执行的
constructor(executor) {
// 执行器接收2个函数resolve,reject,这2个函数是用来更改promise的状态的
// 一旦promise状态确定就不可更改
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
// executor(this.resolve, this.reject)
}
status = PENDING // promise的状态
value = undefined // 成功之后的值
reason = undefined // 失败之后的值
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
// 用箭头函数的原因是为了解决this的指向问题
// resolve函数是用来更改promise的状态的
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为成功
this.status = FULFILLED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()()
}
}
// resolve函数是用来更改promise的状态的
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为失败
this.status = REJECTED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()()
}
}
then(sucessCallback, failCallback) {
// 主要代码在这里
sucessCallback = sucessCallback ? sucessCallback : value => value
failCallback = failCallback
? failCallback
: reason => {
throw reason
}
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// failCallback(this.reason)
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
// this.sucessCallback.push(sucessCallback)
// this.failCallback.push(failCallback)
this.sucessCallback.push(() => {
// sucessCallback()
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
this.failCallback.push(() => {
// failCallback()
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
}
})
return promise2
}
}
// x 是前一个then方法里面的回调的返回值
function resolvePromise(promise2, x, resolve2, reject2) {
if (promise2 === x) {
return reject2(
new TypeError('Chaining cycle detected for promise #')
)
}
if (x instanceof MyPromise) {
// x 是promise对象
// x.then((value) => resolve2(value), (reason) => reject2(reason))
x.then(resolve2, reject2)
} else {
// x 是普通值
resolve2(x)
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
let p1 = new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// resolve('成功')
reject('失败')
})
// then方法的链式调用
// 后面then方法里面的回调函数拿到的值,是前一个then方法里面回调函数的返回值
// then方法是promise对象里的方法,想要实现then方法的链式调用,
// 需要每一个then方法都要返回promise对象才可以
p1.then() // 等同于then((value)=>value)
.then() // 等同于then((value)=>value)
.then(
value => {
console.log(value)
},
reason => {
console.log(reason)
}
)
9、Promise.all([])方法的实现
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
// 接收执行器,执行器是立即执行的
constructor(executor) {
// 执行器接收2个函数resolve,reject,这2个函数是用来更改promise的状态的
// 一旦promise状态确定就不可更改
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
// executor(this.resolve, this.reject)
}
status = PENDING // promise的状态
value = undefined // 成功之后的值
reason = undefined // 失败之后的值
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
// 用箭头函数的原因是为了解决this的指向问题
// resolve函数是用来更改promise的状态的
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为成功
this.status = FULFILLED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()()
}
}
// resolve函数是用来更改promise的状态的
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为失败
this.status = REJECTED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()()
}
}
then(sucessCallback, failCallback) {
// 主要代码在这里
sucessCallback = sucessCallback ? sucessCallback : value => value
failCallback = failCallback
? failCallback
: reason => {
throw reason
}
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// failCallback(this.reason)
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
// this.sucessCallback.push(sucessCallback)
// this.failCallback.push(failCallback)
this.sucessCallback.push(() => {
// sucessCallback()
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
this.failCallback.push(() => {
// failCallback()
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
}
})
return promise2
}
// 静态方法,由类本身来调用
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 index = 0; index < array.length; index++) {
// 拿到当前值
let current = array[index]
if (current instanceof MyPromise) {
// promise对象
current.then(
value => addData(index, value),
reason => reject(reason)
)
} else {
// 普通值
addData(index, array[index])
}
}
})
}
}
// x 是前一个then方法里面的回调的返回值
function resolvePromise(promise2, x, resolve2, reject2) {
if (promise2 === x) {
return reject2(
new TypeError('Chaining cycle detected for promise #')
)
}
if (x instanceof MyPromise) {
// x 是promise对象
// x.then((value) => resolve2(value), (reason) => reject2(reason))
x.then(resolve2, reject2)
} else {
// x 是普通值
resolve2(x)
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
function p1() {
return new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
setTimeout(() => {
resolve('p1')
// reject('失败')
}, 2000)
})
}
function p2() {
return new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
resolve('p2')
// reject('失败')
})
}
MyPromise.all(['a', 'b', p1(), p2(), 'c']).then(
value => {
// value ==> ['a', 'b', 'p1', 'p2', 'c']
console.log(value)
},
error => {
console.log(error)
}
)
10、Promise.resolve 方法的实现
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
// 接收执行器,执行器是立即执行的
constructor(executor) {
// 执行器接收2个函数resolve,reject,这2个函数是用来更改promise的状态的
// 一旦promise状态确定就不可更改
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
// executor(this.resolve, this.reject)
}
status = PENDING // promise的状态
value = undefined // 成功之后的值
reason = undefined // 失败之后的值
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
// 用箭头函数的原因是为了解决this的指向问题
// resolve函数是用来更改promise的状态的
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为成功
this.status = FULFILLED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()()
}
}
// resolve函数是用来更改promise的状态的
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为失败
this.status = REJECTED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()()
}
}
then(sucessCallback, failCallback) {
// 主要代码在这里
sucessCallback = sucessCallback ? sucessCallback : value => value
failCallback = failCallback
? failCallback
: reason => {
throw reason
}
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// failCallback(this.reason)
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
// this.sucessCallback.push(sucessCallback)
// this.failCallback.push(failCallback)
this.sucessCallback.push(() => {
// sucessCallback()
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
this.failCallback.push(() => {
// failCallback()
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
}
})
return promise2
}
// 静态方法,由类本身来调用
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 index = 0; index < array.length; index++) {
// 拿到当前值
let current = array[index]
if (current instanceof MyPromise) {
// promise对象
current.then(
value => addData(index, value),
reason => reject(reason)
)
} else {
// 普通值
addData(index, array[index])
}
}
})
}
// 静态方法,由类本身来调用
static resolve(value) {
// 传入的值value是否为promise对象?
if (value instanceof MyPromise) {
// 传入的值value是promise对象
return value
} else {
// 传入的值,就是普通的值
return new MyPromise(resolve => resolve(value))
}
}
}
// x 是前一个then方法里面的回调的返回值
function resolvePromise(promise2, x, resolve2, reject2) {
if (promise2 === x) {
return reject2(
new TypeError('Chaining cycle detected for promise #')
)
}
if (x instanceof MyPromise) {
// x 是promise对象
// x.then((value) => resolve2(value), (reason) => reject2(reason))
x.then(resolve2, reject2)
} else {
// x 是普通值
resolve2(x)
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
function p1() {
return new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
resolve('p1')
// reject('失败')
})
}
MyPromise.resolve(10).then(value => console.log(value))
MyPromise.resolve(p1()).then(value => console.log(value))
11、finally 方法的实现
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
// 接收执行器,执行器是立即执行的
constructor(executor) {
// 执行器接收2个函数resolve,reject,这2个函数是用来更改promise的状态的
// 一旦promise状态确定就不可更改
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
// executor(this.resolve, this.reject)
}
status = PENDING // promise的状态
value = undefined // 成功之后的值
reason = undefined // 失败之后的值
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
// 用箭头函数的原因是为了解决this的指向问题
// resolve函数是用来更改promise的状态的
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为成功
this.status = FULFILLED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()()
}
}
// resolve函数是用来更改promise的状态的
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为失败
this.status = REJECTED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()()
}
}
then(sucessCallback, failCallback) {
// 主要代码在这里
sucessCallback = sucessCallback ? sucessCallback : value => value
failCallback = failCallback
? failCallback
: reason => {
throw reason
}
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// failCallback(this.reason)
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
// this.sucessCallback.push(sucessCallback)
// this.failCallback.push(failCallback)
this.sucessCallback.push(() => {
// sucessCallback()
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
this.failCallback.push(() => {
// failCallback()
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
}
})
return promise2
}
// 静态方法,由类本身来调用
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 index = 0; index < array.length; index++) {
// 拿到当前值
let current = array[index]
if (current instanceof MyPromise) {
// promise对象
current.then(
value => addData(index, value),
reason => reject(reason)
)
} else {
// 普通值
addData(index, array[index])
}
}
})
}
// 静态方法,由类本身来调用
static resolve(value) {
// 传入的值value是否为promise对象?
if (value instanceof MyPromise) {
// 传入的值value是promise对象
return value
} else {
// 传入的值,就是普通的值
return new MyPromise(resolve => resolve(value))
}
}
finally(callback) {
return this.then(
value => {
return MyPromise.resolve(callback()).then(() => value)
// callback()
// return value
},
reason => {
return MyPromise.resolve(callback()).then(() => {
throw reason
})
// callback()
// throw reason
}
)
}
}
// x 是前一个then方法里面的回调的返回值
function resolvePromise(promise2, x, resolve2, reject2) {
if (promise2 === x) {
return reject2(
new TypeError('Chaining cycle detected for promise #')
)
}
if (x instanceof MyPromise) {
// x 是promise对象
// x.then((value) => resolve2(value), (reason) => reject2(reason))
x.then(resolve2, reject2)
} else {
// x 是普通值
resolve2(x)
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
function p1() {
return new MyPromise((resolve, reject) => {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
setTimeout(() => {
resolve('p1成功')
// reject('p2失败')
}, 2000)
})
}
function p2() {
return new MyPromise((resolve, reject) => {
resolve('p2成功')
// reject('失败')
})
}
// finally()方法特点:
// 1、无论promise对象的最终状态是成功的,还是失败的,finally方法中的回调函数始终会被执行一次
// 2、finally方法的后面可以使用链式调用then方法,拿到当前promise对象返回的结果
p2()
.finally(() => {
console.log('finally方法')
return p1()
})
.then(
value => console.log(value),
reason => console.log(reason)
)
12、catch 方法的实现
创建一个 MyPromise.js 的文件,代码如下:
const PENDING = 'pending' // promise的状态 等待
const FULFILLED = 'fulfilled' // promise的状态 成功
const REJECTED = 'rejected' // promise的状态 失败
class MyPromise {
// 接收执行器,执行器是立即执行的
constructor(executor) {
// 执行器接收2个函数resolve,reject,这2个函数是用来更改promise的状态的
// 一旦promise状态确定就不可更改
try {
executor(this.resolve, this.reject)
} catch (error) {
this.reject(error)
}
// executor(this.resolve, this.reject)
}
status = PENDING // promise的状态
value = undefined // 成功之后的值
reason = undefined // 失败之后的值
sucessCallback = [] // then()方法里面的成功的回调
failCallback = [] // then()方法里面的失败的回调
// 用箭头函数的原因是为了解决this的指向问题
// resolve函数是用来更改promise的状态的
resolve = value => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为成功
this.status = FULFILLED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.value = value
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.sucessCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.sucessCallback.shift()()
}
}
// resolve函数是用来更改promise的状态的
reject = reason => {
// promise的状态不是等待状态的时候,要阻止程序向下执行
if (this.status !== PENDING) return
// promise的状态更改为失败
this.status = REJECTED
// 保存成功之后的值,方便在then()方法中,拿到对应的值
this.reason = reason
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 然后 把值 传递给then()方法里面对应的sucessCallback, failCallback函数
while (this.failCallback.length) {
// this.sucessCallback 里面存储一个或多个then方法的sucessCallback, failCallback函数
// this.sucessCallback.shift() 就是每一个then方法对应的sucessCallback, failCallback函数
// 需要把每一个都取出来传递给对应的then方法
this.failCallback.shift()()
}
}
then(sucessCallback, failCallback) {
// 主要代码在这里
sucessCallback = sucessCallback ? sucessCallback : value => value
failCallback = failCallback
? failCallback
: reason => {
throw reason
}
let promise2 = new MyPromise((resolve2, reject2) => {
// MyPromise的执行器函数是立即执行的
// 下面的代码也必须立即执行,所以正好放在执行器函数里面
// 判断promise的状态
if (this.status === FULFILLED) {
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else if (this.status === REJECTED) {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// failCallback(this.reason)
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
} else {
// 异步执行,2秒后在执行,来确定promise的状态是成功还是失败
// 因为多次调用 then 方法,所以需要把多个then方法里面的成功的回调和失败的回调,
// 用数组保存起来才可以
// this.sucessCallback.push(sucessCallback)
// this.failCallback.push(failCallback)
this.sucessCallback.push(() => {
// sucessCallback()
setTimeout(() => {
try {
// 成功的回调,同时把成功的值传递给sucessCallback
// 成功的值在调用resolve()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = sucessCallback(this.value) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
this.failCallback.push(() => {
// failCallback()
setTimeout(() => {
try {
// 失败的回调,同时把失败的值传递给failCallback
// 失败的值在调用reject()的时候传递过来的
// 判断X值是普通值还是promise对象
// 如果是普通值 直接调用resolve
// 如果是promise对象,查看promise对象返回的结果
// 再根据peomise对象返回的结果
// 决定调用resolve 还是调用reject
let x = failCallback(this.reason) // 前一个then方法里面的回调的返回值
resolvePromise(promise2, x, resolve2, reject2)
// resolve2(x) // 把前一个then方法里面的回调的返回值x 传递给后一个then方法里面的回调函数中
} catch (error) {
reject2(error)
}
}, 0)
})
}
})
return promise2
}
// 静态方法,由类本身来调用
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 index = 0; index < array.length; index++) {
// 拿到当前值
let current = array[index]
if (current instanceof MyPromise) {
// promise对象
current.then(
value => addData(index, value),
reason => reject(reason)
)
} else {
// 普通值
addData(index, array[index])
}
}
})
}
// 静态方法,由类本身来调用
static resolve(value) {
// 传入的值value是否为promise对象?
if (value instanceof MyPromise) {
// 传入的值value是promise对象
return value
} else {
// 传入的值,就是普通的值
return new MyPromise(resolve => resolve(value))
}
}
finally(callback) {
return this.then(
value => {
return MyPromise.resolve(callback()).then(() => value)
// callback()
// return value
},
reason => {
return MyPromise.resolve(callback()).then(() => {
throw reason
})
// callback()
// throw reason
}
)
}
catch(failCallback) {
return this.then(undefined, failCallback)
}
}
// x 是前一个then方法里面的回调的返回值
function resolvePromise(promise2, x, resolve2, reject2) {
if (promise2 === x) {
return reject2(
new TypeError('Chaining cycle detected for promise #')
)
}
if (x instanceof MyPromise) {
// x 是promise对象
// x.then((value) => resolve2(value), (reason) => reject2(reason))
x.then(resolve2, reject2)
} else {
// x 是普通值
resolve2(x)
}
}
module.exports = MyPromise
创建一个 index.js 文件,文件内导入 MyPromise.js 的文件,同时使用该文件,代码如下:
const MyPromise = require('./MyPromise')
function p1() {
return new MyPromise((resolve, reject) => {
resolve('p1成功')
reject('失败')
})
}
p1()
.then(value => console.log(value))
.catch(reason => console.log(reason))
结语:
来拉钩教育训练营学习已经有二周了,在没有来之前,我都是回家之后打游戏(游戏名:斗战神),来到这里之后才发现居然还有很多大佬也在学习,真的很惊讶,本人自身水平垃圾的一批,再不学习,以后可能一直就是混吃等死的状态了
- 首先来说,拉钩的课程很干,每个视频很短,都是干货,讲师没有一句废话,视频内容覆盖比较广,布置的作业也比较符合实际,导师也会及时批改,然后一周或两周必有直播,直播都会回答学习过程中所遇到的问题和新的内容
- 其次来说,每个班都有班级群,群里居然还有5年或6年的前端开发的大佬(⊙▽⊙); 班主任和导师也在群里,有任何问题都可以在群里@导师,班级群真的很活跃
- 最后来说一句,如果有其他人也是在打游戏混日子,不如来拉钩教育训练营,尝试着改变一下自己目前所处的环境