简单理解 Promise 的实现原理+自己手写一个 Promise

文章内容输出来源:拉勾教育大前端高薪训练营
文章说明:文章内容为学习笔记,学徒之心,仅为分享; 如若有误,请在评论区指出,如若您觉得文章内容对您有一点点帮助,请点赞、关注、评论,共享

上一篇: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 #<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 #<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 #<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 #<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 #<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 #<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年的前端开发的大佬(⊙▽⊙); 班主任和导师也在群里,有任何问题都可以在群里@导师,班级群真的很活跃
  • 最后来说一句,如果有其他人也是在打游戏混日子,不如来拉钩教育训练营,尝试着改变一下自己目前所处的环境
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350