• 2021/04/10 温习

导航

[[深刻01] 执行上下文](https://juejin.im/post/684490...
[[深刻02] 原型链](https://juejin.im/post/684490...
[[深刻03] 继承](https://juejin.im/post/684490...
[[深刻04] 事件循环](https://juejin.im/post/684490...
[[深刻05] 柯里化 偏函数 函数记忆](https://juejin.im/post/684490...
[[深刻06] 隐式转换 和 运算符](https://juejin.im/post/684490...
[[深刻07] 浏览器缓存机制(http缓存机制)](https://juejin.im/post/684490...
[[深刻08] 前端平安](https://juejin.im/post/684490...
[[深刻09] 深浅拷贝](https://juejin.im/post/684490...
[[深刻10] Debounce Throttle](https://juejin.im/post/684490...
[[深刻11] 前端路由](https://juejin.im/post/684490...
[[深刻12] 前端模块化](https://juejin.im/post/684490...
[[深刻13] 观察者模式 公布订阅模式 双向数据绑定](https://juejin.im/post/684490...
[[深刻14] canvas](https://juejin.im/post/684490...
[[深刻15] webSocket](https://juejin.im/post/684490...
[[深刻16] webpack](https://juejin.im/post/684490...
[[深刻17] http 和 https](https://juejin.im/post/684490...
[[深刻18] CSS-interview](https://juejin.im/post/684490...
[[深刻19] 手写Promise](https://juejin.im/post/684490...
[[深刻20] 手写函数](https://juejin.im/post/684490...

[[react] Hooks](https://juejin.im/post/684490...

[[部署01] Nginx](https://juejin.im/post/684490...
[[部署02] Docker 部署vue我的项目](https://juejin.im/post/684490...
[[部署03] gitlab-CI](https://juejin.im/post/684490...

[[源码-webpack01-前置常识] AST形象语法树](https://juejin.im/post/684490...
[[源码-webpack02-前置常识] Tapable](https://juejin.im/post/684490...
[[源码-webpack03] 手写webpack - compiler简略编译流程](https://juejin.im/post/684490...
[[源码] Redux React-Redux01](https://juejin.im/post/684490...
[[源码] axios ](https://juejin.im/post/684490...
[[源码] vuex ](https://juejin.im/post/684490...
[[源码-vue01] data响应式 和 初始化渲染 ](https://juejin.im/post/684490...
[[源码-vue02] computed 响应式 - 初始化,拜访,更新过程 ](https://juejin.im/post/684490...

前置常识

一些单词

race:较量,比赛Settled:完结execute:执行executor:执行者detected:检测

promise温习

  • 办法

    • promise.then() ---------------------------- 返回新的promise
    • promise.catch() --------------------------- 返回新的promise
    • promise.finally() -------------------------- 不论状态如何都会执行
    • promise.all() ------------------------------ 所有resolve则fulfilled,一个reject则rejected
    • promise.any() ---------------------------- 一个resolve则fulfilled,所有reject则rejected
    • promsie.race() ---------------------------- 第一个resolve则fulfiled,第一个reject则rejected
  • 特点

    • 对象的状态不受外界影响,只有异步操作的后果才能够决定以后是哪一种状态,任何其余操作都不能扭转这个状态
    • 状态一旦扭转就不会再变,任何时候都能够失去这个后果
  • <font color=red>毛病</font>

    • 无奈勾销promise,一旦新建就会立刻执行,中途无奈勾销
    • 如果不设置回调,外部抛出的谬误,不会反馈到内部
    • 当处于pending状态时,无奈得悉以后停顿到哪一个阶段 ( 刚开始?行将完结?)
  • Promise的用法

    const promise = new Promise(function(resolve, reject) {// ... some codeif (/* 异步操作胜利 */){  resolve(value);} else {  reject(error);}});promise.then(function(value) {// success}, function(error) {// failure});阐明:(1) Promise构造函数承受一个 ( 函数 ) 作为参数(2) ( 参数函数 ) 又承受两个函数作为参数 ( resolve函数 ) 和 ( reject函数 )(3) resolve()   - 函数是在状态由 pending->fulfilled 时,即胜利时调用,并将异步操作的后果作为参数传递进来  - resolve()函数的参数,除了是失常的 ( 值 ) 以外,还能够是一个 ( promise实例 )(4) reject()   - 函数是在状态由 pending->rejected时,即失败时调用,并将异步操作报出的谬误作为参数传递进来  - reject()函数的参数,通常是 ( Error对象 ) 的实例(5) then() 办法承受两个函数作为参数  - 第一个参数函数在resolve时被调用  - 第二个参数函数在reject时被调用,参数别离是终值和拒因,第二个参数函数可选
  • resolve()

    • resolve()和reject()两个函数并不会终止promise,前面的代码还是会执行
    • <font color=red>通常用 return resolve() return reject() 这样的形式完结promise构造函数代码的运行</font>
    • <font color=blue>resolve() 函数的参数是一个promise实例的状况</font>
    let count = 1setInterval(() => {console.log(count++)}, 1000)const p1 = new Promise(function (resolve, reject) {setTimeout(() => {  console.log('p1中的代码开始执行')  reject(new Error('fail'))}, 3000)})const p2 = new Promise(function (resolve, reject) {setTimeout(() => {  console.log('p2中的代码开始执行');  resolve(p1)}, 1000)})p2.then(result => console.log(result)).catch(error => console.log(error))剖析:(1) p2的状态在 1s 后扭转为胜利,resolve(p1)的参数p1还是一个promise,导致p2的状态生效(2) p2的状态生效,则p2的状态由p1决定(3) p1的状体在 3s 后扭转为失败, reject(new Error('fail')),所以在 3s 后,p2的状态也变成了失败(4) p2的失败状态由 p2.catch()捕捉
  • then()

    • <font color=red>返回一个新的promise实例,因而能够采纳链式写法</font>
    • <font color=blue>如果then()办法链式调用,上一个then()可能返回的是一个promise实例,则后一个then()的回调函数须要期待前一个then()状态扭转后才会调用</font>
  • catch()

    • <font color=red>返回一个新的promise实例,次要作用是捕捉promise过程中的谬误</font>
    • <font color=blue>catch()办法返回的是一个promise对象,因而.catch()前面能够持续调用.then()</font>
    • catch()是.then(null, rejection).then(undefined, rejection)的别名,用于指定产生谬误时的回调函数
    • 只有是catch()后面的then()和promise外部抛出的谬误都能被catch()捕捉
    • 留神:

      • 一个在then()中只须要增加胜利状态后的回调,而失败的状态由catch()来负责捕捉
  • finally()

    • <font color=red>不论promise对象最初是什么状态,都会执行的操作</font>
    • <font color=blue>finally()的回调函数不承受任何参数,因为finally()的回调函数中的操作和状态无关</font>
  • all()

    • 所有resolve()则fulfilled,一个reject()则rejected
  • any()

    • 一个resolve()则fulfilled,所有reject()则rejected

      • 和all()相同
  • race()

    • 一个resolve()则fulfilled,一个reject()则rejected
  • allSettled()

    • 在所有参数的实例都返回后果时,包装实例才会完结
    • 比方期待所有申请实现,无论成功失败,都完结loading动画

手写Promise

class Promise {  constructor(executor) {    // 参数不是函数,报错    if (typeof executor !== 'function') {      throw new TypeError(`Promise resolver ${executor} is not a function`)    }    this.init() // 初始化值    try {      executor(this.resolve, this.reject)    } catch (err) {      // 应用 try...catch 的目标是为了把executor()中的谬误抛出给then的回调去捕捉      this.reject(err)    }  }  init = () => {    this.value = null // 终值    this.reason = null // 拒因    this.state = Promise.PENDING // 状态    this.onFulfilledCallbacks = [] // 胜利回调, 在then()办法中push,resolve()时执行    this.onRejectedCallbacks = [] // 失败回调,在then()办法中push,reject()时执行  }  resolve = (value) => {    // 胜利后的一系列操作 (状态的扭转,胜利回调的执行 )    // 状态的扭转:pending -> fulfilled    // console.log(this.constructor === Promise) // true    // this 在箭头函数中,作用域绑定在父级执行上下文,即定义时所在的对象    // 即this相当于父级的this,这里又是在勾走函数中,所以this指向了实例对象     if (this.state === Promise.PENDING) {      this.state = Promise.FULFILLED      this.value = value      this.onFulfilledCallbacks.forEach(fn => fn(this.value))      // 当promise的参数函数中有异步操作时,then办法会优先于resolve()或者reject()先执行      // 这样就是导致执行then()办法时,状态是pending状态,因为状态的扭转是在resolve()或reject()中扭转的,而他们因为异步都没执行      // 这是须要用一个数组来存储未来才会执行的onFulfilled函数      // 这里push进onFulfilledCallbacks的函数,将在resolve()函数中去执行    }  }  reject = (reason) => {    // 失败后的一系列操作 (状态的扭转,失败回调的执行 )    // 状态的扭转:pending -> rejected    if (this.state === Promise.PENDING) {      this.state = Promise.REJECTED      this.reason = reason      this.onRejectedCallbacks.forEach(fn => fn(this.reason))    }  }  then = (onFulfilled, onRejected) => {    // 参数校验,穿透成果,即then不传任何参数具备穿透成果    if (typeof onFulfilled !== 'function') {      onFulfilled = value => value    }    // 参数校验,穿透成果,即then不传任何参数具备穿透成果    if (typeof onRejected !== 'function') {      onRejected = reason => {        throw reason      }    }    // then()办法返回的是一个新的 promse 实例    // 因为返回新的promise实例,能够能够实现链式调用    let promise2 = new Promise((resolve2, reject2) => {      // 执行onFulfilled函数的条件      if (this.state === Promise.FULFILLED) {        setTimeout(() => {          // 这里两头的then()办法中的回调 onFulfilled() 函数是有返回值的          // 两头then()参数函数onFulfilled()的返回值,会被当做下一个then回调的参数传入          try {            const x = onFulfilled(this.value)            Promise.resolvePromise(promise2, x, resolve2, reject2)          } catch (err) {            reject2(err)          }        })      }      if (this.state === Promise.REJECTED) {        setTimeout(() => {          try {            const x = onRejected(this.reason)            Promise.resolvePromise(promise2, x, resolve2, reject2)          } catch (err) {            reject2(err)          }        })      }      if (this.state === Promise.PENDING) {        // 如果状态是 pending        // 当promise的参数函数中有异步操作时,then办法会优先于resolve()或者reject()先执行        // 这样就是导致执行then()办法时,状态是pending状态,因为状态的扭转是在resolve()或reject()中扭转的,而他们因为异步都没执行        // 这时须要用一个数组来存储未来才会执行的onFulfilled函数        // 这里push进onFulfilledCallbacks的函数,将在resolve()函数中去执行        this.onFulfilledCallbacks.push((value) => {          // 这里依然须要应用setTimeout,因为这个函数是在resolve()中执行的,如果resolve()前面任而后同步代码,要保障同步代码先执行          setTimeout(() => {            try {              const x = onFulfilled(value)              Promise.resolvePromise(promise2, x, resolve2, reject2)            } catch (err) {              reject2(err)            }          })        })        this.onRejectedCallbacks.push((reason) => {          setTimeout(() => {            try {              const x = onRejected(reason)              Promise.resolvePromise(promise2, x, resolve2, reject2)            } catch (err) {              reject2(err)            }          })        })      }    })    return promise2  }}// 这里应用动态属性,是为了防止 魔法字符串Promise.PENDING = 'pending'Promise.FULFILLED = 'fulfilled'Promise.REJECTED = 'rejected'Promise.resolvePromise = function (promise2, x, resolve, reject) {  // x 与 promise2 相等  if (promise2 === x) {    reject(new TypeError('chainning cycle detected for promise'))  }  // x 是 Promise  if ( x instanceof Promise) {    x.then(value => {      // resolve(value)      Promise.resolvePromise(promise2, value, resolve, reject)    }, reason => {      reject(reason)    })  }   else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {    // x 为对象或函数    try {      const then = x.then      if (typeof then === 'function') {        then.call(          x,          value => {            if (called) return            called = true            MyPromise.resolvePromise(promise2, value, resolve, reject)          },          reason => {            if (called) return            called = true            reject(reason)          }        )      } else {        if (called) return        called = true        resolve(x)      }    } catch (e) {      if (called) return      called = true      reject(e)    }  } else {    resolve(x)  }}const promise = new Promise((resolve, reject) => {  // throw new Error('出错了')  console.log(1)  setTimeout(() => {    console.log(4)    resolve(6)    console.log(5)  })  console.log(2)})  .then(    value => {      console.log(value, 'value')      return new Promise(resolve => {        resolve(new Promise(resolve3 => {          resolve3(7)        }))      })    },    reason => {      console.log(reason, 'reason')    })  .then(    value => {      console.log(value, 'vvvvvvvvvvvv')    }, reason => {      console.log(reason)    })console.log(3)// then  // then中的两个参数回调函数须要异步,setTimeout解决  // 如果promise参数函数外部抛出谬误,须要在then()中捕捉 => try ... catch  // 如果promise中存在异步,then的回调不会执行 => 因为在执行then办法的时,state === 'pending' 不满足执行then两个回调的任何一个,而当setTimeout中的 resolve() 执行的时,then执行过了就不会再继续执行

new Promise()的参数必须是函数,非函数时会报错

原生:new Promise(1)TypeError: Promise resolver 1 is not a function模仿实现:class Promise {  constructor(executor) {    if (typeof executor !== 'function') {      // 参数必须是函数,不是函数抛出谬误      throw new TypeError(`Promise resolver ${executor} is not a function`)    }    executor(this.resolve, this.reject)  }}const promise = new Promise()// TypeError: Promise resolver undefined is not a function

resolve()办法的次要作用

  • (1) 把状态 ( <font color=red>status</font> ) 从 ( <font color=red>pending -> fulfilled</font> )
  • (2) 把终值 ( <font color=red>value</font> ) 赋值为 resolve()函数传入的 ( <font color=red>参数</font> )
  • (3) 把 ( <font color=red>onFulfilledCallback数组</font> ) 中的函数,依此取出执行

    • 如果promise中存在异步操作时,then()比resolve()先执行
    • 所以在then()办法中,须要向onFulfilledCallback数组中push进一个未来在resolve()中才会执行的函数

    rejected()办法的次要作用

  • (1) 把状态 ( <font color=red>status</font> ) 从 ( <font color=red>pending -> rejected</font> )
  • (2) 把拒因 ( <font color=red>value</font> ) 赋值为 reject()函数传入的 ( <font color=red>参数</font> )
  • (3) 把 ( <font color=red>onRejectedCallback数组</font> ) 中的函数,依此取出执行

    • 如果promise中存在异步操作时,then()比resolve()先执行
    • 所以在then()办法中,须要向onFulfilledCallback数组中push进一个未来在reject()中才会执行的函数
    class Promise {constructor(executor) {  if (typeof executor !== 'function') {    // 参数必须是函数,不是函数抛出谬误    throw new TypeError(`Promise resolver ${executor} is not a function`)  }  this.init()  executor(this.resolve, this.reject)}init = () => {  this.value = null // 终值,初始化  this.reason = null // 拒因,初始化  this.status = Promise.PENDING // 状态,初始化时pending  this.onFulfilledCallbacks = [] // 胜利回调, 在then()办法中push,resolve()时执行  this.onRejectedCallbacks = [] // 失败回调,在then()办法中push,reject()时执行}resolve = (value) => {  if (this.status === Promise.PENDING) {    this.status = Promise.FULFILLED    this.value = value    this.onFulfilledCallbacks.forEach(fn => fn(value))  }}reject = (reason) => {  if (this.status === Promise.PENDING) {    this.status === Promise.REJECTED    this.reason = reason    this.onRejectedCallbacks.forEach(fn => fn(resaon))  }}then = (onFulfilled, onRejected) => {  if (this.status === Promise.FULFILLED) {    onFulfilled(this.value)  }  if (this.status === Promise.REJECTED) {    onRejected(this.reason)  }  if (this.status === Promise.PENDING) {    this.onFulfilledCallbacks.push((value) => onFulfilled(value))    this.onRejectedCallbacks.push((reason) => onRejected(reason))  }}}Promise.PENDING = 'pending'Promise.FULFILLED = 'fulfilled'Promise.REJECTED = 'rejected'const promise = new Promise((resolve, reject) => {setTimeout(() => {  resolve(1)})}).then(value => {console.log(value)}, reason => {console.log(reason)})

then()办法没有传参时

  • 须要重写 onFulfilled函数,返回以后的终值 this.value
  • 须要重写 onRejected函数,返回以后的拒因 this.reason,并抛出

    then = (onFulfilled, onRejected) => {      if (typeof onFulfilled !== this.FUNCTION) {          // 没传onFulfilled参数,就重写该函数          // 将调用参数原样返回          // 这里没有间接写 (typeof onFulfilled !== 'function') 避免魔法字符串          onFulfilled = value => value       }      if (typeof onRejected !== this.FUNCTION) {           // 没传onRejected参数,就重写该函数           // 抛出reason          onRejected = reason => {              throw reason          }      }      if (this.status === this.FULFILLED) {          // 是fulfilled状态是,才执行onFulfilled函数,参数是以后的终值          // 即状态扭转时为胜利时,增加的回调函数          // 这里传参和没有传参都会执行,没传参是执行重写过后的onFulfilled          onFulfilled(this.value)      }      if (this.status === this.REJECTED) {          onRejected(this.reason)      }  }

then()保障执行程序1

  • <font color=red>then()须要在同步代码执行完后,then()中的回调函数能力执行</font>

    console.log(1)const promise = new Promise((resolve, reject) => {console.log(2)resolve(5)console.log(3)}).then(value => {console.log(value)}, reason => {console.log(reason)})console.log(4)问题:如何保障执行程序是  12345解决:then()是异步办法,即then()办法的参数回调须要在resolve()或reject()办法执行后才执行,用 ( 定时器 ) 解决阐明:如果不必定时器执行程序是 then = (onFulfilled, onRejected) => {  if (typeof onFulfilled !== Promise.FUNCTION) {    onFulfilled = value => value  }  if (typeof onRejected !== Promise.FUNCTION) {    onRejected = reason => reason  }  if (this.status === Promise.FULFILLED) {    setTimeout(() => { // 用setTimeout()来模仿异步执行onFulfilled,保障同步代码执行后再执行onFulfilled      onFulfilled(this.value)    })  }  if (this.status === Promise.REJECTED) {    setTimeout(() => { // 用setTimeout()来模仿异步执行onRejected,保障同步代码执行后再执行onRejected      onRejected(this.reason)    })  }  if (this.status === Promise.PENDING) {    this.onFulfilledCallbacks.push((value) => onFulfilled(value))    this.onRejectedCallbacks.push((reason) => onRejected(reason))  }}

then()保障执行程序2

  • <font color=red>当promise中有有异步代码时,then()办法会比resolve()先执行,此时statuss='pending'状态</font>
  • <font color=red>而在then办法中并未增加状态是pending状态时的相干操作时,then()中的两个回调都不会执行</font>

    console.log(1)new Promise((resolve, reject) => {  console.log(2)  setTimeout(() => resolve()) // 当这里有异步操作时,下面的代码打印只有 123,留神 4 并未打印 // 起因是then()办法在resolve()办法前执行了,因为resolve是异步的,导致 then() 中的状态还是 pending 状态 // 而在then办法中并为增加状态是pending状态时的相干操作}).then(() =>  console.log(4))console.log(3)问题:打印出了123,然而并未打印4剖析:1. 起因是then()办法在resolve()办法前执行了,因为resolve是异步的,导致 then() 中的状态还是 pending 状态2. 而在then办法中并为增加状态是pending状态时的相干操作解决:1. 在then()办法中增加pending状态下的相干判断    - 并向 onFulfilledCallbacks 数组中push一个方办法,该方中去调用 onFulfilled 办法,参数是以后的value    - 并向 onRejectedCallbacks 数组中 push 一个办法,该方中去调用 onRejected 办法,参数是以后的reason2. 在resolve()办法中去循环 onFulfilledCallbacks 数组,并执行外面的函数,实参是 this.value2. 在reject()办法中去循环 onRejectedCallbacks 数组,并执行外面的函数,实参是 this.reasonthen = (onFulfilled, onRejected) => {      ...      if (this.status === this.PENDING) {          // pending状态push函数到onFulfilledCallbacks数组          this.onFulfilledCallbacks.push(value => onFulfilled(value))           this.onRejectedCallbacks.push(reason => onRejected(reason))      }  } resolve = (value) => {      if (this.status === this.PENDING) {          this.status = this.FULFILLED          this.value = value          this.onFulfilledCallbacks.forEach(fn => fn(this.value)) // 执行数组中的函数,并传入实参      }  }reject = (reason) => {      if (this.status === this.PENDING) {          this.status = this.REJECTED          this.reason = reason          this.onRejectedCallbacks.forEach(fn => fn(this.reason))      }  }

then()保障执行程序3

console.log(1)new Promise((resolve, reject) => {    console.log(2)    setTimeout(() => {        resolve()        console.log(4) // 要保障4比5先执行,因为4是同步代码    })}).then(() =>  console.log(5))console.log(3)问题:下面代码输入 12354 , 而真正的promise应该输入  12345剖析:因为resolve()前面还有同步代码,要保障前面的同步代码先执行解决:在向 onFulfilledCallbacks数组中push办法时,要再用 setTimeout包装,让resolve()前面的代码先执行    then = (onFulfilled, onRejected) => {       ...        if (this.status === this.PENDING) {            this.onFulfilledCallbacks.push(value => {                setTimeout(() => { // 再用setTimeout包装,保障resolve()前面的代码先于 then的回调函数 执行                    onFulfilled(value)                }, 0)            })            this.onRejectedCallbacks.push(reason => {                setTimeout(() => {                    onRejected(reason)                }, 0)            })        }    }

then() 的链式调用

  • <font color=red>then()办法返回的是新的promise实例,留神不是原来的,所以能够链式调用</font>
  • <font color=red>新的promise中参数函数的resolve的是onFufiled函数执行后返回的值</font>

    then = (onFulfilled, onRejected) => {  // 参数校验,穿透成果,即then不传任何参数具备穿透成果  if (typeof onFulfilled !== Promise.FUNCTION) {    onFulfilled = value => value  }  // 参数校验,穿透成果,即then不传任何参数具备穿透成果  if (typeof onRejected !== Promise.FUNCTION) {    onRejected = reason => reason  }  const promise2 = new Promise((resolve2, reject2) => {    if (this.status === Promise.FULFILLED) {      setTimeout(() => {        const x = onFulfilled(this.value)        // 将onFulfilled函数的返回值作为resolve()的参数,传给新的 then() 办法        resolve2(x)      })    }    if (this.status === Promise.REJECTED) {      setTimeout(() => {        const x = onRejected(this.reason)        reject2(x)      })    }    if (this.status === Promise.PENDING) {      this.onFulfilledCallbacks.push((value) => {        setTimeout(() => {          const x = onFulfilled(value)          resolve2(x)        })      })      this.onRejectedCallbacks.push((reason) => {        setTimeout(() => {          const x = onRejected(reason)          reject2(x)        })      })    }  })  return promise2}
    更具体then = (onFulfilled, onRejected) => {      if(typeof onFulfilled !== 'function') {        onFulfilled = (value) => value      }      if(typeof onRejected !== 'function') {        onRejected = (reason) => {          throw reason        }      }      const promise2 = new Promise((resolve, reject) => {        if (this.status === Promise.FULFILLED) {          setTimeout(() => {            try {              const x = onFulfilled(this.value) // 将onFulfilled函数的返回值作为resolve()的参数,传给新的 then() 办法              resolve(x) // promise2的resolve的机会            } catch(err) {              reject(err) // promise2的reject的机会            }          })        }        if (this.status === Promise.REJECTED) {          setTimeout(() => {            try {              const x = onRejected(this.reason)              resolve(x)            } catch (err) {              reject(err)            }          })        }        if (this.status === Promise.PENDING) {          this.onFulfilledCallbacks.push((value) => {            setTimeout(() => {              try {                const x = onFulfilled(value)                resolve(x)              } catch(err) {                reject(err)              }            })          })          this.onRejectedCallbacks.push((reason) => {            setTimeout(() => {              try {                const x = onRejected(reason)                resolve(x)              } catch(err) {                reject(err)              }            })          })        }      })      return promise2    }

Promise.all()模仿实现

  • p = Promsie.all([p1, p2, p3])
  • 返回值:Promise.all() 返回一个新的promise实例
  • 参数:

    • ( <font color=red>参数</font> ) 是一个 ( <font color=red>数组</font> ) 或者是具备 ( <font color=red>Iterator</font> ) 接口类型的数据,成员都是promsie实例
    • 如果不是promsie实例就会调用Promsie.resolve()转成promsie实例
  • 作用:

    • 如果所有参数数组成员的状态,都变成了fulfilled,则整个状态变成fulfilled

      • 此时 p1,p2,p3中resolve()的返回值,将组成一个数组,传递给p的回调函数
    • 如果有一个参数数组成员的状态变成了rejected,则整个状态变成了rejected

      • 此时,第一个被回绝的reject()的返回值,会传递给p的回调函数
  • Promise.all()返回的是一个新的promise,即能够应用then获取resolve和reject的后果
  • 参数是一个数组或者具备Iterator接口的数据
  • 如果参数数组成员不是promise,就会被Promise.resolve()转成promise对象
  • resolve的机会是所有参数成员都变成fulfilled状态时
  • reject的机会是只有有一个rejected状态时

    Promise.all = (promises) => {
    // 返回一个新的promise实例
    return new Promise((resolve, reject) => {

      const arr = []  let count = 0 // 记录fulfilled状态的promise个数  const promiseArr = Array.from(promises) // 参数除了数组还能够是具备Iterator接口的数据类型  const len = promiseArr.length  for (let i = 0; i < len; i++) {      Promise.resolve(promiseArr[i]).then(value => { // 如果参数不是promise,会调用Promise.resolve()转成promise          count ++ // 进入这里,示意胜利的回调,即fulfilled状态          arr[i] = value // 将该胜利的promise装进数组          if (count === len) {               console.log(count, 'count')              resolve(arr)              // 如果count和数组总长度相等,阐明都是fulfilled状态了              // 所有resolve的机会就是所有都变成fulfilled状态是resolve          }      }, reject) // 这里写的不欠缺,请看上面的最新补充  }

    })
    }

    const a = Promise.resolve(1)
    const b = Promise.resolve(2)
    const c = new Promise(resolve => {
    setTimeout(() => {

      resolve(33)

    })
    })

    Promise.all([a, b, c]).then(value => console.log(value, 'value'))

2021/4/7批改 Promise.all 模仿实现

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Document</title></head><body>  <script>    // 手写 Promise.all    // 1. Promise.all返回的是一个新的promise    // 2. Promise.all的参数是一个数组,成员是promise对象,如果不是promise对象会先把参数转成promise    // 3. 所有成员fulfilled则整个状态变成 fulfilled    // 4. 一个rejected则整个状态变成 rejected    const promise1 = Promise.resolve(1)    const promise2 = Promise.resolve(2)    const promise3 = Promise.resolve(3)    const promise4 = Promise.reject(new Error('出错了'))    Promise.all2 = (promises) => {      return new Promise((resolve, reject) => { // Promise.all()返回一个新的promise对象        const promisesArr = Array.from(promises)        const len = promisesArr.length        let count = 0        const results = []        for (let i = 0; i < len; i++) {          Promise.resolve(promisesArr[i]).then(value => { // 如果参数不是promise则先转成promise            count++            results.push(value)            if (results.length === len) {              resolve(results) // 当数组整个遍历完后,都没产生谬误的状况下,resolve(results) 整个终值数组            }          }, reason => reject(reason)) // 只有一个产生谬误,整个 reject最先产生的拒因        }      })    }    Promise.all2([promise1, promise2, promise3]) // fulfilled      .then(value => console.log(value))      .catch(err => console.log(err))    Promise.all2([promise1, promise2, promise3, promise4]) // rejected      .then(value => console.log(value))      .catch(err => console.log(err))  </script></body></html>

Proimse.race()模仿实现

Promise.race = (promises) => {      return new Promise((resolve, reject) => {        const promiseArr = Array.from(promises)        const len = promises.length        for(let i = 0; i < len; i++) {          Promise.resolve(promiseArr[i]).then(value => {            resolve(value) // 间接resolve第一个then是胜利时的回调函数接管到的终值          })        }      })    }

总结遇到的一些面试题 2021/04/10

(1) promise面试题1

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Document</title></head><body>  <script>    console.log(1)    setTimeout(() => { // 定时器 A      console.log(2);      Promise.resolve().then(() => { // Promise D        console.log(3)      })    })    new Promise((resolve, reject) => { // Promise B      console.log(4)      resolve(5)    }).then((data) => {      console.log(data)    })    setTimeout(() => { // 定时器 C      console.log(6)    })    console.log(7)/****         答案:1 4 7 5 2 3 6             剖析:         1. 第一次事件循环         同步工作:1         宏工作:[A, C]         微工作:[B]         输入:1 4 7             2. 第二次事件循环         遍历所有微工作[B] => 5         取出第一个宏工作[A] => 2 , 并将微工作D增加进工作队列,此时微工作队列 [D]         输入:5 2             3. 第三次事件循环         遍历所有微工作[D] => 3         取出第一个红工作[C] -> 6         输入:3 6*/  </script></body></html>

(2) promise面试题2

<!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <meta name="viewport" content="width=device-width, initial-scale=1.0">  <title>Document</title></head><body>  <script>    console.log(1)    // A promise    new Promise((resolve) => {      console.log(2)      resolve()      console.log(3)    }).then(res => { // E then      console.log(4)      // C 定时器      setTimeout(() => console.log(5))    })    console.log(6)    // B 定时器    setTimeout(() => {      console.log(7)      // D promise      new Promise((resolve) => {        console.log(8)        resolve()      }).then(() => console.log(9)) // F then    })    console.log(10)    /**     * 第一轮 Event loop     * 1 => 同步工作,进入函数调用栈,立刻执行     * A => A的回调立刻执行     *      2 => 同步工作,立刻执行     *      E => 微工作,进入微工作队列     *      3 => 同步工作,立刻执行     * 6 => 同步工作,立刻执行     * B => 宏工作,B的回调进入宏工作队列     * 10 => 同步工作,立刻执行     * 此时执行状况如下:     * 输入:1,2,3,6,10     * 微工作:[E]     * 宏工作:[B]     *     * 第二轮 Event loop     * 清空微工作队列,取出宏工作队列的第一个成员     * E => 4 同步工作,立刻执行     *      C 宏工作,进入宏工作队列,此时的宏工作队列 [B, C]     * B => 7 同步工作,立刻执行     *      D promise的回调立刻执行     *        => 8 同步工作,立刻执行     *        => F 微工作,进入微工作队列,此时的微工作队列 [F]     * 此时执行状况如下:     * 输入:4,7,8     * 微工作:[F]     * 宏工作:[C]     *     * 第三轮 Event loop     * 清空微工作队列,取出宏工作队列的第一个成员     * F => 9 同步工作,立刻执行     * C => 5 同步工作,立刻执行     *     * 总的输入程序:1,2,3,6,10,4,7,8,9,5     */  </script></body></html>

材料

手写promise https://segmentfault.com/a/11...
手写promise https://juejin.im/post/684490...