日拱一卒终有尽, 功不唐捐终入海

一、Promise 类核心逻辑实现

思路:

  1. Promise 就是一个类 =>
  2. 需要有一个立即执行的回调 =>
  3. 传递两个参数resolve和reject(函数) =>
  4. resolve和reject能够改变状态 =>
  5. Promise 有三个特有的状态,并且不能被再次修改 =>
  6. 提供链式调用的 then 方法 =>
  7. 传递两个参数,分别执行失败/成功回调 =>
  8. 成功需要传递成功的参数,失败需要传递失败的原因 =>
  9. 导出 myPromise

定义 myPromise 方法:

//实现 Promise 核心功能// myPromise 存在三个独有的状态
const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败// 创建一个名为 myPromise 的类
class myPromise {// 通过构造函数 constructor 来接收这个执行器(executor)constructor(executor) { // 立即执行// 传入两个参数,因为是箭头函数接收,所以用 this.executor(this.resolve, this.reject)}// 设定初始状态status = PENDING// 成功之后的值value = undefined// 失败之后的原因reason = undefinedresolve = (val) => {// 状态不可更改if (this.status !== PENDING) return// 改变状态 等待 => 成功this.status = FULFILLED// 保存成功之后的值this.value = val}reject = (val) => {// 状态不可更改if (this.status !== PENDING) return// 改变状态 等待 => 失败this.status = REJECTED// 保存失败之后的原因this.reason = val}// 定义 then 方法, 接收两个参数 - 成功回调/失败回调then(successCallBack, failCallBack) {// 判断状态if (this.status === FULFILLED) { // 调用成功回调// 传入成功的值successCallBack(this.value)} else if (this.status === REJECTED) { // 调用失败回调// 传入失败的原因failCallBack(this.reason)}}
}// 导出
module.exports = myPromise

调用 myPromise:

// 调用 myPromiseconst myPromise = require("./myPromise")const promise = new myPromise((resolve, reject) => {resolve('成功')reject('失败')
})promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})
// => 成功

二、Promise 类中加入异步逻辑

调用 myPromise:

const myPromise = require("./02-myPromise")
const promise = new myPromise((resolve, reject) => {// resolve('成功')// 执行器中使用异步, resolve 方法会延迟执行(setTimeout 是宏任务, Promise 是微任务)setTimeout(() => {resolve('成功')}, 500)// reject('失败')
})// then 方法会立即执行, 此时的 myPromise 中, status 状态是 pending 状态, 所以不会发生成功/失败回调
promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})
// => 无打印结果

思路:

  1. 设置两个变量,初始值为 undefined
  2. 两个变量分别用来储存(then 方法中) pending 状态时的成功/失败回调
  3. 执行异步的 resolve/reject 时,判断变量是否存在
  4. 如果存在,则立即执行 成功/失败回调

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {executor(this.resolve, this.reject)}status = PENDINGvalue = undefinedreason = undefined// 成功之后回调successCallBack = undefined// 失败之后的回调failCallBack = undefinedresolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = val// 如果成功的回调是否存在 如果存在 调用this.successCallBack && this.successCallBack(this.value)}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = val// 如果失败的回调是否存在 如果存在 调用this.failCallBack && this.failCallBack(this.reason)}then(successCallBack, failCallBack) {if (this.status === FULFILLED) {successCallBack(this.value)} else if (this.status === REJECTED) {failCallBack(this.reason)} else { // 等待状态(异步)// 储存成功回调this.successCallBack = successCallBack// 储存失败回调this.failCallBack = failCallBack}}
}module.exports = myPromise

三、实现 then 方法多次调用添加多个处理函数

调用 myPromise - 多个同步函数:

// 调用 myPromiseconst myPromise = require("./03-myPromise")const promise = new myPromise((resolve, reject) => {resolve('成功')reject('失败')
})promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})// => 成功 成功 成功

调用 myPromise - 多个异步步函数:

// 调用 myPromiseconst myPromise = require("./03-myPromise")const promise = new myPromise((resolve, reject) => {// resolve('成功')setTimeout(() => {resolve('成功')}, 500)// reject('失败')
})// 上一节中:设置了两个变量分别用来储存(then 方法中) pending 状态时的成功/失败回调,但是只能存储一个 成功/失败的回调
// 所以导致多个异步函数只能返回一个异步结果
promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})
promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})
promise.then(value => {console.log(value)
}, reason => {console.log(reason)
})
// => 成功

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {executor(this.resolve, this.reject)}status = PENDINGvalue = undefinedreason = undefined// 成功之后回调(接收多个处理函数)successCallBack = []// 失败之后的回调(接收多个处理函数)failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = val// 如果成功的回调是否存在 如果存在 调用// this.successCallBack && this.successCallBack(this.value)// while 循环 - 指定条件为真时循环执行代码块// shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值while (this.successCallBack.length) { // 立即执行this.successCallBack.shift()(this.value)}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = val// 如果失败的回调是否存在 如果存在 调用// this.failCallBack && this.failCallBack(this.reason)while (this.successCallBack.length) { // 立即执行this.successCallBack.shift()(this.reason)}}then(successCallBack, failCallBack) {if (this.status === FULFILLED) {successCallBack(this.value)} else if (this.status === REJECTED) {failCallBack(this.reason)} else { // 等待状态(异步)// 可以储存多个 成功回调this.successCallBack.push(successCallBack)// 可以储存多个 失败回调this.failCallBack.push(failCallBack)}}
}module.exports = myPromise

四、实现 then 方法的链式调用

调用 myPromise - 实现 then 方法多次链式调用:

// 调用 myPromiseconst myPromise = require("./04-myPromise")const promise = new myPromise((resolve, reject) => {resolve('成功')// reject('失败')
})promise.then(value => {console.log(value)return 100})// then 方法链式调用.then(value => {console.log(value)// => Cannot read property 'then' of undefined(报错)})

思路:

then 方法链式调用的参数是上一个 then 方法返回的 全新 promise 对象

  1. 在 then 方法中创建一个 promise 对象,并传递出去
  2. 将(上一个)then 方法 的返回值传递给下一个 then 方法
  3. 判断(上一个)then 方法的返回值
  4. 如果是普通值,直接调用 resolve()方法
  5. 如果是 promise 对象,则根据结果选择调用 resolve() / reject() 方法

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {executor(this.resolve, this.reject)}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {this.successCallBack.shift()(this.value)}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {this.successCallBack.shift()(this.reason)}}then(successCallBack, failCallBack) {// 创建一个 promise 对象let promise2 = new myPromise((resolve, reject) => { // 传递一个 立即执行 的执行器if (this.status === FULFILLED) {// successCallBack(this.value)// 储存 (上一个)then 的返回值let x = successCallBack(this.value)// 将值传递给 下一个 then 方法的回调函数// resolve(x)// 引用公共方法(解析 promise) resolvePromise(x, resolve, reject)} else if (this.status === REJECTED) {failCallBack(this.reason)} else {this.successCallBack.push(successCallBack)this.failCallBack.push(failCallBack)}})// 返回 promise 对象, 供下一个 then 方法调用return promise2}
}// 创建公共方法(解析 Promise)
function resolvePromise(x, resolve, reject) {// 如果是 Promise 对象if (x instanceof myPromise) { // 调用Promise 对象的 then 方法// x.then(//   // 如果 promise 对象是成功的//   (value) => {//     resolve(value)//   },//   // 如果 promise 对象是失败的//   (reason) => {//     reject(reason)//   }// )// 简写 =>x.then(resolve, reject)// 如果是普通值} else { // 直接调用 resolve 方法resolve(x)}
}module.exports = myPromise

调用 myPromise - then 方法返回普通值Promise 对象

// 调用 myPromiseconst myPromise = require("./04-myPromise")const promise = new myPromise((resolve, reject) => {resolve('成功')// reject('失败')
})// 创建一个 Promise 对象
function other () { // 返回一个 Promise 对象return new myPromise((resolve, reject) => { // 传入一个执行器resolve('other')// reject()})
}promise.then(value => {console.log(value)// return 100// 返回 other 函数的调用return other()})// then 方法链式调用.then(value => {console.log(value)// => 成功  100// => 成功  other})

五、then 方法识别 返回Promise 本身

调用 Promise - 实现 then 方法返回 promise 对象本身:

  // 调试 (原生)promiseconst promise2 = new Promise((resolve, reject) => {resolve(100)})let p = promise2.then(function(value) { // 传递一个成功的回调函数console.log(value)// 返回 then 方法 返回的 promise 对象return p // 发生了 promise 的循环调用//  Chaining cycle detected for promise => 检测到promise的链接周期})

思路:

  1. 成功回调返回的 promise 对象和 then 方法返回的 promise 对象做比较
  2. 如果相同,执行失败回调,并返回失败的原因
  3. 将比较的判断转为异步执行,确保在 then 方法返回 Promise 对象后执行

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {executor(this.resolve, this.reject)}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {this.successCallBack.shift()(this.value)}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {this.successCallBack.shift()(this.reason)}}then(successCallBack, failCallBack) {let promise2 = new myPromise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => { // 异步执行,确保得到 promise2(then 方法返回的 promise 对象)let x = successCallBack(this.value)// 将 then 方法返回的 promise 对象传入resolvePromise(promise2, x, resolve, reject)}, 0)} else if (this.status === REJECTED) {failCallBack(this.reason)} else {this.successCallBack.push(successCallBack)this.failCallBack.push(failCallBack)}})return promise2}
}// 接收 then 方法返回的 promise 对象
function resolvePromise(promise2, x, resolve, reject) {// 比较 `成功回调`返回的 promise 对象 和 `then 方法`返回的 promise 对象if(x === promise2) { // 如果相同// 执行失败回调return reject( // 返回失败的原因new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof myPromise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = myPromise

调用 myPromise - 实现 then 方法返回 promise 对象本身:

// 调用 myPromiseconst myPromise = require("./05-myPromise")const promise = new myPromise((resolve, reject) => {resolve('成功')// reject('失败')
})function other () {return new myPromise((resolve, reject) => {resolve('other')// reject()})
}// 通过变量 p , 储存 then 方法返回的 promise 对象
let p = promise.then(value => {console.log(value)// 循环调用: 将 then 方法返回的 promise 对象, 进行返回return p})// 循环调用的错误会传递到下一个 then 方法的 失败回调函数当中p.then(value => {console.log(value)}, reason => { // 传递一个失败的回调函数// 获取报错信息内容console.log(reason)// => TypeError: Chaining cycle detected for promise #<Promise>})

六、捕获错误及 then 方法的补充

1. 捕获错误:

  • 在 promise 中,如果运行错误,需要在 then 方法回调中捕获错误的原因
  • 在 then 方法中,如果执行错误,需要在下一个 then 回调中捕获到错误的原因

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {try { // 尝试运行executor(this.resolve, this.reject)} catch (error) { // 如果运行失败// 执行失败函数, 传递错误的原因this.reject(error)}}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {this.successCallBack.shift()(this.value)}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {this.successCallBack.shift()(this.reason)}}then(successCallBack, failCallBack) {let promise2 = new myPromise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => {try { // 执行let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) { // 如果执行失败// 指定 reject 方法, 传递失败的原因reject(error)}}, 0)} else if (this.status === REJECTED) {failCallBack(this.reason)} else {this.successCallBack.push(successCallBack)this.failCallBack.push(failCallBack)}})return promise2}
}function resolvePromise(promise2, x, resolve, reject) {if (x === promise2) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof myPromise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = myPromise

调用 Promise - 实现 promisethen 方法 执行失败后抛出错误原因:

// 调用 myPromiseconst myPromise = require("./05-myPromise")const promise = new myPromise((resolve, reject) => {// 主动抛出错误// throw new Error('executer error')resolve('成功')// reject('失败')
})promise.then(value => {throw new Error('then error')console.log(value)
}, reason => {console.log(reason) // 捕获错误// => Error: executer error
}).then(value => {console.log(value)}, reason => { // 捕获错误console.log(reason.message)// => Error: then error})

2. then 方法的补充

  • 完善 then方法 的失败回调
  • 完善then 方法 的异步回调

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {try {executor(this.resolve, this.reject)} catch (error) {this.reject(error)}}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {// this.successCallBack.shift()(this.value)// 不需要传值, 立即执行this.successCallBack.shift()()}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {// this.successCallBack.shift()(this.reason)// 不需要传值, 立即执行this.successCallBack.shift()()}}then(successCallBack, failCallBack) {let promise2 = new myPromise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else if (this.status === REJECTED) {// failCallBack(this.reason)// 同成功回调, 实现异步/多次链式调用/识别返回 promise 对象本身/执行失败后抛出错误原因setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else {// this.successCallBack.push(successCallBack)// push 整个函数,不然内部无法判断执行是否成功this.successCallBack.push(() => {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})// this.failCallBack.push(failCallBack)// push 整个函数,不然内部无法判断执行是否成功this.failCallBack.push(() => {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})}})return promise2}
}function resolvePromise(promise2, x, resolve, reject) {if (x === promise2) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof myPromise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = myPromise

调用 myPromise - 实现 then 方法失败回调 / 异步:

// 调用 myPromiseconst myPromise = require("./06.2-myPromise")const promise = new myPromise((resolve, reject) => {setTimeout(() => {resolve('成功')}, 1000)// reject('失败')
})promise.then(value => {console.log(value)return 10
}, reason => {console.log(reason)return 20
}).then(value => {console.log(value)// => 成功 10}, reason => {// console.log(reason)// => 失败 20})

七、将 then 方法的参数变为可选参数

调用 Promise - 实现 then 方法不传参:

  // 调试 promise(原生)const promise2 = new Promise((resolve, reject) => {resolve(100)})promise2.then().then().then(value => console.log(value))// => 100// then 方法的参数是非必须的// 如果 then 方法未接收到参数, 则会依次向后传递, 直到传递给有回调函数的 then 方法

思路:

  1. 监听 then 方法的 成功 / 失败 回调 是否存在参数
  2. 如果存在, 就用起自身
  3. 如果不存在,则给 then 方法插入参数(成功的值 / 失败的原因),并向后传递

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {try {executor(this.resolve, this.reject)} catch (error) {this.reject(error)}}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}then(successCallBack, failCallBack) { // 判断 successCallBack failCallBack 是否存在// 如果存在, 就用 then 的成功回调 自身// 如果不存在, 就插入一个形参 value(成功的值), 并将 value 返回出去(向后传递)successCallBack = successCallBack ? successCallBack : value => value// 如果存在, 就用 then 的失败回调 自身// 如果不存在, 就插入一个形参  reason(错误的原因), 并将  reason 返回出去(向后传递)// failCallBack = failCallBack ? failCallBack : reason => { //  抛出错误//   throw reason// }failCallBack = failCallBack ? failCallBack : reason => reason //  抛出错误let promise2 = new myPromise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else if (this.status === REJECTED) {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else {this.successCallBack.push(() => {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})this.failCallBack.push(() => {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})}})return promise2}
}function resolvePromise(promise2, x, resolve, reject) {if (x === promise2) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof myPromise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = myPromise

调用 myPromise - 实现 then 方法参数为空:

// 调用 myPromiseconst myPromise = require("./07-myPromise")const promise = new myPromise((resolve, reject) => {// resolve('成功')reject('失败')
})promise.then().then().then(value => { // 执行回调函数console.log(value)// => 成功}, reason => { // 执行失败回调console.log(reason)// => 失败})

八、Promise.all 方法的实现

调用 Promise - 实现 Promise.all 方法:

// 调用 promiseconst p1 = new Promise((resolve, reject) => {setTimeout(() => {resolve('1')}, 1000)// reject('失败')
})const p2 = new Promise((resolve, reject) => {resolve('2')
})Promise.all(['a', 'b', p1, p2, 'c'])
// Promise.all 传入的是一个数组,并且参数可以是对象,也可以是普通值
// Promise.all 返回的也是一个 Promise 对象, 所以可以使用 then 方法进行链式调用
.then(value => { // 全部执行成功, 才能成功console.log(value)// => [ 'a', 'b', '1', '2', 'c' ]// 得到的结果的顺序 也一定会是 传入的顺序(上面 p2 应该是先于 p1 执行)}, reason => { // 有一个失败, 即失败console.log(reason)})

思路:

  1. 创建静态方法 all
  2. 对 all 方法接收的参数数组做循环
  3. 通过参数是普通值,直接返回;如果是Promise 对象,将执行的结果返回
  4. 返回的顺序需要和执行的顺序相同(返回数组的脚标)
  5. 有一个执行失败,直接执行失败回调
  6. 循环时无法等待异步执行,处理异步执行问题

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {try {executor(this.resolve, this.reject)} catch (error) {this.reject(error)}}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}then(successCallBack, failCallBack) {successCallBack = successCallBack ? successCallBack : value => valuefailCallBack = failCallBack ? failCallBack : reason => reasonlet promise2 = new myPromise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else if (this.status === REJECTED) {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else {this.successCallBack.push(() => {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})this.failCallBack.push(() => {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})}})return promise2}// 声明一个静态方法 all, 接收数组作为参数static all(array) {// 定义结果数组let result = []// 定义一个变量,记录调用 addData (处理传递参数)的次数let index = 0// 返回一个 promise 对象, 传入执行器return new myPromise((resolve, reject) => {// 定义一个方法, 将值传递数组中function addData(key, value) {result[key] = valueindex++if (index === array.length) { // 传入参数的执行次数 === 添加值到结果数组的次数// 执行 resolve 方法,将 结果数组 传递回去resolve(result)}}// 循环数组for (let i = 0; i < array.length; i++) {let current = array[i]// 类型判断if (current instanceof myPromise) { // Promise 对象current.then( // 执行 current 的 Promise 对象// 传入成功回调,  将执行的结果添加到 结果数组中value => addData(i, value),// 传入失败回调, 如果有一个失败, 直接调用失败的方法, 并且传递失败的原因reason => reject(reason))} else { // 普通值// 直接放到结果数组当中addData(i, array[i])}}// 循环结束后, 执行 resolve 方法, 并传递结果数组resolve(result)})}
}function resolvePromise(promise2, x, resolve, reject) {if (x === promise2) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof myPromise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = myPromise

调用 myPromise - all 方法:

// 调用 myPromiseconst myPromise = require("./08-myPromise")const p1 = new myPromise((resolve, reject) => {setTimeout(() => {resolve('p1')}, 2000)// reject('失败')
})const p2 = new myPromise((resolve, reject) => {resolve('p2')
})Promise.all(['a', 'b', p1, p2, 'c']).then(value => {console.log(value)// => [ 'a', 'b', 'p1', 'p2', 'c' ]}, reason => {console.log(reason)})

九、Promise.resolve 方法

调用 Promise - 实现 Promise.resolve 方法:

// 调用 promiseconst p = new Promise((resolve, reject) => {resolve('hello')// reject('失败')
})Promise.resolve(10)// Promise.resolve 的参数如果是普通值, 会将传入的参数 包裹在 Promise 对象中来返回, 所以能够被 then 方法链式调用.then(value => {console.log(value)// => 10}, reason => {console.log(reason)})Promise.resolve(p)// Promise.resolve 的参数如果是Promise 对象, 会将 其 直接返回.then(value => {console.log(value)// => hello}, reason => {console.log(reason)})

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {try {executor(this.resolve, this.reject)} catch (error) {this.reject(error)}}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}then(successCallBack, failCallBack) {successCallBack = successCallBack ? successCallBack : value => valuefailCallBack = failCallBack ? failCallBack : reason => reasonlet promise2 = new myPromise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else if (this.status === REJECTED) {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else {this.successCallBack.push(() => {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})this.failCallBack.push(() => {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})}})return promise2}static all(array) {let result = []let index = 0return new myPromise((resolve, reject) => {function addData(key, value) {result[key] = valueindex++if (index === array.length) {resolve(result)}}for (let i = 0; i < array.length; i++) {let current = array[i]if (current instanceof myPromise) {current.then(value => addData(i, value),reason => reject(reason))} else {addData(i, array[i])}}resolve(result)})}// 创建 resolve 的静态方法static resolve(value) {// 判断是否是 Promise 的实例对象if (value instanceof myPromise) { // 如果参数是对象// 直接返回 Promise 对象return value} else { // 如果是普通值// 创建一个 promise 对象, 传入一个执行器return new myPromise(resolve =>{ // 将 value 包裹起来resolve(value)})}}
}function resolvePromise(promise2, x, resolve, reject) {if (x === promise2) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof myPromise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = myPromise

调用 myPromise - resolve 方法:

// 调用 myPromiseconst myPromise = require("./09-myPromise")const p1 = new myPromise((resolve, reject) => {setTimeout(() => {resolve('hello')// reject('失败')}, 1000)
})Promise.resolve(100).then(value => {console.log(value)// => 100}, reason => {console.log(reason)})Promise.resolve(p1).then(value => {console.log(value)// => hello}, reason => {console.log(reason)})

十、Promise.finally 方法

  • 无论 finally 方法成功还是失败,Promise.finally 方法都会被执行
  • finally 可以被 then 方法获取到最终返回的结果

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {try {executor(this.resolve, this.reject)} catch (error) {this.reject(error)}}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}then(successCallBack, failCallBack) {successCallBack = successCallBack ? successCallBack : value => valuefailCallBack = failCallBack ? failCallBack : reason => reasonlet promise2 = new myPromise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else if (this.status === REJECTED) {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else {this.successCallBack.push(() => {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})this.failCallBack.push(() => {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})}})return promise2}// 创建一个 finally 方法, 并传入一个回调函数finally(callback) {// 通过 then 方法获取当前 Promise 的状态// 返回 then 方法作为回调的 Promise 对象return this.then(// 成功回调value => {// callback()// // 向下一个 then 方法传递成功的值// return value// 通过 resolve 方法, 等待 callback 执行完成后再返回 成功的值(包裹成 Promise 对象)return myPromise.resolve(callback()).then(() => {return value})},// 失败回调reason => {// callback()// // 向下一个 then 方法传递失败的原因// // throw reason// return reason// 通过 resolve 方法, 等待 callback 执行完成后再返回 失败的原因(包裹成 Promise 对象)return myPromise.resolve(callback()).then(() => {return reason})})}static all(array) {let result = []let index = 0return new myPromise((resolve, reject) => {function addData(key, value) {result[key] = valueindex++if (index === array.length) {resolve(result)}}for (let i = 0; i < array.length; i++) {let current = array[i]if (current instanceof myPromise) {current.then(value => addData(i, value),reason => reject(reason))} else {addData(i, array[i])}}resolve(result)})}static resolve(value) {if (value instanceof myPromise) {return value} else {return new myPromise(resolve => {resolve(value)})}}
}function resolvePromise(promise2, x, resolve, reject) {if (x === promise2) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof myPromise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = myPromise

调用 myPromise - finally 方法:

// 调用 myPromiseconst myPromise = require("./10-myPromise")const p1 = new myPromise((resolve, reject) => {setTimeout(() => {resolve('成功')// reject('失败')}, 1000)
})// 无论成功失败, 都会执行后面的内容
p1.finally(()=> {console.log('finally')// => finally
}).then(value => {console.log(value)// => 成功}, reason => {console.log(reason)})

十一、Promise.catch 方法

  • 如果 then 方法中不执行失败回调,catch 就会捕获失败回调,从而将失败的原因传入 catch 方法的回调函数当中
  • 只需要在 catch 方法中,执行 then 方法,在成功函数传入 undefined,失败的函数传入 失败回调

定义 myPromise 方法:

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'class myPromise {constructor(executor) {try {executor(this.resolve, this.reject)} catch (error) {this.reject(error)}}status = PENDINGvalue = undefinedreason = undefinedsuccessCallBack = []failCallBack = []resolve = (val) => {if (this.status !== PENDING) returnthis.status = FULFILLEDthis.value = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}reject = (val) => {if (this.status !== PENDING) returnthis.status = REJECTEDthis.reason = valwhile (this.successCallBack.length) {this.successCallBack.shift()()}}then(successCallBack, failCallBack) {successCallBack = successCallBack ? successCallBack : value => valuefailCallBack = failCallBack ? failCallBack : reason => reasonlet promise2 = new myPromise((resolve, reject) => {if (this.status === FULFILLED) {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else if (this.status === REJECTED) {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)} else {this.successCallBack.push(() => {setTimeout(() => {try {let x = successCallBack(this.value)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})this.failCallBack.push(() => {setTimeout(() => {try {let x = failCallBack(this.reason)resolvePromise(promise2, x, resolve, reject)} catch (error) {reject(error)}}, 0)})}})return promise2}finally(callback) {return this.then(value => {return myPromise.resolve(callback()).then(() => {return value})},reason => {return myPromise.resolve(callback()).then(() => {return reason})})}// 创建一个 catch 方法, 只需要传入一个失败回调catch(failCallBack) {// 成功的函数不传, 失败的函数传入失败的回调return this.then(undefined, failCallBack)}static all(array) {let result = []let index = 0return new myPromise((resolve, reject) => {function addData(key, value) {result[key] = valueindex++if (index === array.length) {resolve(result)}}for (let i = 0; i < array.length; i++) {let current = array[i]if (current instanceof myPromise) {current.then(value => addData(i, value),reason => reject(reason))} else {addData(i, array[i])}}resolve(result)})}static resolve(value) {if (value instanceof myPromise) {return value} else {return new myPromise(resolve => {resolve(value)})}}
}function resolvePromise(promise2, x, resolve, reject) {if (x === promise2) {return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))}if (x instanceof myPromise) {x.then(resolve, reject)} else {resolve(x)}
}module.exports = myPromise

调用 myPromise - catch 方法:

// 调用 myPromiseconst myPromise = require("./11-myPromise")const p1 = new myPromise((resolve, reject) => {// resolve('成功')reject('失败')
})p1.then(value => {console.log(value)}).catch(reason => console.log(reason))// => 失败

下一篇:ECMAScript 新特性

手撕Promise源码相关推荐

  1. 手撕OpenCV源码之resize(INTER_AREA)

    手撕OpenCV源码之resize<INTER_AREA> resize在modules/imgproc/src/文件件中,首先看resize API的函数实现: void resize( ...

  2. 【手写 Promise 源码】第八篇 - 完善 Promise 并通过 promise-aplus-tests 测试

    一,前言 上一篇,实现 Promise 对返回值 x 各种情况的分析和处理,主要涉及以下几个点: 回顾了相关的 Promise A+ 规范内容: 根据 Promise A+ 规范描述和要求,实现了核心 ...

  3. 手撕Java源码系列之Map接口

    Map简介 #Map是以Key和Value进行存储的,这点就是与Collection做一个区别.Map的Key不可重复,但是value可以重复.而Collection最直观的感受就是其子接口Set,仅 ...

  4. JavaWeb三大组件之一——Filter过滤器源码解析(全面手撕Filter源码,需要耐心看完)

    什么是Filter? 本文所说的Filter是JavaWeb中常见常使用的过滤器.Filter的作用是拦截前端发送给后端的请求,一般是用于权限过滤.日志记录.图片转换.加密.数据压缩等操作. 大致流程 ...

  5. 手撕LongAdder-add()源码

    最近喜欢上阅读国外大牛写的源码,真的感觉每一步都是精华,膜拜膜拜. 特此将代码的每一步解析总结出来分享给大家~~~ /*** Adds the given value.** @param x the ...

  6. 手撕Iterator源码

    public abstract class AbstractList<E>{//操作数(操作了添加数据.删除数据,操作数都会++)protected transient int modCo ...

  7. 【手撕MyBatis源码】MyBatis映射体系

    文章目录 映射工具MetaObject 基本功能 底层结构 获取属性值的流程 ResultMap结果集映射 手动映射 自动映射 嵌套子查询 循环依赖 懒加载 原理 内部结构 Bean代理过程 联合查询 ...

  8. Node进阶——之事无巨细手写Koa源码

    作者 rocYoung Koa是一个基于Node.js的Web开发框架,特点是小而精,对比大而全的Express(编者按:此处是相对来说,国内当然是有Egg.js和ThinkJS),两者虽然由同一团队 ...

  9. Node进阶—事无巨细手写Koa源码

    作者 rocYoung Koa是一个基于Node.js的Web开发框架,特点是小而精,对比大而全的Express(编者按:此处是相对来说,国内当然是有Egg.js和ThinkJS),两者虽然由同一团队 ...

最新文章

  1. GSA+麦肯锡开年首场线上活动:汽车半导体要变天?
  2. SQL Server 2012 新特性:新增和修改函数
  3. 前端学习(1439):vue的helloworld
  4. 使用CNN进行情感分类
  5. 联想Y470为什么安装不上CentOS7 x86_64的系统?
  6. html5css3网站设计基础教程答案,HTML5+CSS3网站设计基础教程_动手实践源代码
  7. 计算机桌面壁纸希望,电脑励志的图片桌面壁纸
  8. 2sum,3sum,4sum问题总结
  9. 华为防火墙忘记密码,使用console口更改密码
  10. 图片批量加边框,详细操作步骤
  11. 主板知识详解:主板结构
  12. influxdb删除column
  13. 国际网页短信系统平台搭建后台功能篇|移讯云短信系统
  14. uIP中文协议文档:Ch01
  15. C语言拼图游戏——Windows下基于EasyX且支持鼠标与键盘操作
  16. Edge 安装 CSDN 浏览器助手
  17. SPSS Modeler建立ODBC数据源使用数据库文件
  18. 天助自助者----与君共勉
  19. Vlookup函数和Sumif函数详解
  20. iOS开发——高级技术内购服务

热门文章

  1. 华为云会议接口java查询会议鉴权Token查询会议录制
  2. 游戏音乐外包中策划应该怎么做?
  3. arduino串口中断数据
  4. loadrunner(三)
  5. Keynote教程 – 将演示文稿发布到WordPress博客中
  6. 信安66部——OA办公系统部署
  7. android开发技术路线图
  8. 新书推荐 | Flutter技术入门与实战(第2版)
  9. 中国电信业重组方案敲定!——新的格局拭目以待
  10. App 启动流程全解析