promise

博客介绍了Promise的相关内容,包括源码中Promise的三种状态常量,即pending(等待态)、resolved(成功态)、rejected(失败态),还提及链式调用的本质是promise的then方法须返回新的promise对象,此外给出了相关应用的转载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

源码

  • Promise的三种状态常量 —— pending:等待态; resolved:成功态; rejected:失败态
  • 链式调用的本质 —— promise的then方法必须返回一个新的promise对象
链式调用的本质:
promise2 = promise1.then(onFulfilled, onRejected)
promise1.then(onFulfilled1, onRejected1).then(onFulfilled2, onRejected2)
复制代码
源码(promise.js):
function Promise (executor) { // 构造函数Promise必须接受一个函数(executor)作为参数
  this.status = 'pending' // 初始状态为pending
  this.value = undefined // 成功的值
  this.reason = undefined // 失败的原因
  this.onResolvedCallbacks = [] // 保存成功回调函数队列(new Promise()时可能会有异步操作),见[案例4]
  this.onRejectedCallbacks = [] // 保存失败回调函数队列(new Promise()时可能会有异步操作)

  resolve = value => { // resovle时的执行函数(把状态变成resolved)
    if (this.status === 'pending') { // 只有等待态 可以改变状态
      this.value = value
      this.status = 'resolved'
      this.onResolvedCallbacks.forEach(fn => fn()) // 异步执行resolve()时,做【发布】操作,见[案例4]
    }
  }
  reject = reason => { // reject时的执行函数(把状态变成rejected)
    if (this.status === 'pending') { // 只有等待态 可以改变状态
      this.reason = reason
      this.status = 'rejected'
      this.onRejectedCallbacks.forEach(fn => fn()) // 异步执行reject()时,做【发布】操作
    }
  }

  try { // new Promise()时, 直接执行executor函数(同步执行)
    executor(resolve, reject) // executor函数包含resolve和reject两个参数(且都为函数)
  } catch (err) { // 如果执行exectuor时出错,就让当前promise变成失败态
    reject(err)
  }
}

/**
* @param {*} promise2  调用then时返回的【新的】promise对象
* @param {*} x  【当前】then中onFulfilled或onRejected函数的返回值
*        若x不为Promise,则x直接作为Promise2的值(即新的onFulfilled或onRejected函数的参数)
*        若x 为 Promise,则promise2的一个回调函数(resolve或reject),会等待该Promise对象(即x)状态变化后才会被调用,且Promise2的状态和x的状态相同
* @param {*} resolve promise2的resolve
* @param {*} reject  promise2的reject
*/
function resolvePromise (promise2, x, resolve, reject) {  
  if (promise2 === x) { // 不能自己等自己,见[案例1]
    return reject(new TypeError('Chaining cycle detected for promise'))
  }

  let called = false  // 防止多次调用(既调成功也调失败),别人的代码可能没有判断 —— 只有等待态 可以改变状态

  if (x !== null && (typeof x === 'object' || typeof x === 'function')) { //【1+】x是对象或函数才有可能是promise
    try { // 尝试取x的then属性,进一步判别x是否为promise,可能会抛异常(这个promise可能是别人乱写的),见[案例5]
      let t = x.then
   
      if (typeof t === 'function') { //【2+】x.then为函数才可能是promise
        /**
        * x可能是promise,直接让x.then执行
        * 1、promise.then() // this指向promise
        * 2、let t = promise.then
        *    t() // this指向全局,通过t.call(x, ...)将this指向x
        * 
        * 以下相当于:
        *     x.then(y => {}, err => {})
        */
        t.call(x, y => { // promise成功的结果,见[案例7]
          if (called) return // 防止多次调用(既调成功也调失败),别人的代码可能没有判断 —— 只有等待态 可以改变状态
          called = true
          resolvePromise(promise2, y, resolve, reject) // 成功的结果可能是promise,需要【递归】解析,直到解析成普通值为止
        }, err => { // promise失败的结果,见[案例6]
          if (called) return
          called = true
          reject(err)
        })
      } else { //【2-】x不为promise(即为普通值,如:x为{then: {}})
        resolve(x)
      }
    } catch (err) {
      if (called) return
      called = true
      reject(err)
    }
  } else { //【1-】x不为promise(即为普通值)
    resolve(x)
  }
}

Promise.prototype.then = function (onFulfilled, onRejected) {
  /**
  * onFulfilled和onRejected是可选参数,如果onFulfilled或onRejected不是函数,必须被忽略
  * 如果onFulfilled不是函数且promise为成功态,则promise2为成功态并返回promise成功的值,见[案例3]
  * 如果onRejected 不是函数且promise为失败态,则promise2为失败态并返回promise失败的值
  */
  onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
  onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }

  let promise2 = new Promise((resolve, reject) => { // 每次调用then时必须返回一个新的promise对象
    switch (this.status) { // this指向promise
      case 'resolved':
        setTimeout(() => {
          try { // 如果onFulfilled或onRejected抛出异常,则promise2必须变为失败态,见[案例2]
            let x = onFulfilled(this.value)
            resolvePromise(promise2, x, resolve, reject)
          } catch (err) {
            reject(err)
          }
        }, 0)
        break
      case 'rejected':
        setTimeout(() => {
          try { // 如果onFulfilled或onRejected抛出异常,则promise2必须变为失败态
            let x = onRejected(this.reason)
            resolvePromise(promise2, x, resolve, reject)
          } catch (err) {
            reject(err)
          }
        }, 0)
        break
      case 'pending':
        this.onResolvedCallbacks.push(() => { // 异步执行resolve()时,做【订阅】操作,见[案例4]
          setTimeout(() => {
            try { // 如果onFulfilled或onRejected抛出异常,则promise2必须变为失败态
              let x = onFulfilled(this.value)
              resolvePromise(promise2, x, resolve, reject)
            } catch (err) {
              reject(err)
            }
          }, 0)
        })
        this.onRejectedCallbacks.push(() => { // 异步执行reject()时,做【订阅】操作
          setTimeout(() => {
            try { // 如果onFulfilled或onRejected抛出异常,则promise2必须变为失败态
              let x = onRejected(this.reason)
              resolvePromise(promise2, x, resolve, reject)
            } catch (err) {
              reject(err)
            }
          }, 0)
        })
        break
    }
  })
  return promise2
}
复制代码
测试代码:
Promise.defer = Promise.deferred = function () {
  let dfd = {}
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve
    dfd.reject = reject
  })
  return dfd
}
module.exports = Promise

// npm install promises-aplus-tests -g
// promises-aplus-tests promise.js
复制代码
案例1:promise2和onFulfilled或onRejected函数返回的结果是同一个对象
let promise = new Promise((resolve, reject) => {
  resolve()
})

let promise2 = promise.then(res => { // 不能自己等自己
  return promise2
})

// TypeError: Chaining cycle detected for promise
复制代码
案例2:如果onFulfilled或onRejected抛出异常,则promise2必须变为失败态
let promise = new Promise((resolve, reject) => {
  resolve()
})
promise2 = promise.then(res => {
  throw new Error('这里抛出一个异常')
})
promise2.then(res => {
  console.log(res)
}, err => {
  console.log(err) // 这里抛出一个异常
})
复制代码
案例3:如果onFulfilled不是函数且promise为成功态,则promise2为成功态并返回promise成功的值
let promise = new Promise((resolve, reject) => {
  resolve('success')
})
promise2 = promise.then('这里的onFulfilled本来是一个函数,但现在不是')
promise2.then(res => {
  console.log(res) // success
}, err => {
  console.log(err)
})
复制代码
案例4:异步执行resolve()时,做【发布、订阅】操作
非异步:
let promise = new Promise((resolve, reject) => {
  resolve('成功') // 非异步执行
})
promise.then(res => { // 状态为resolved,值为成功,直接执行
  console.log(res) // 成功
})

异步:
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('成功') // 异步执行
  }, 1000)
})
promise.then(res => { // 状态为pending,值为undefined,执行【订阅】操作;1s后状态为resolved,值为成功,执行【发布】操作
  console.log(res) // 1s后,成功
})
复制代码
案例5:尝试取x的then属性,进一步判别x是否为promise时,可能会抛异常
let obj = {}
Object.defineProperty(obj, 'then', {
  get () {
    throw new Error('出错')
  }
})
console.log(obj.then) // 出错
复制代码
案例6:x.then失败
let promise = new Promise((resolve, reject) => {
  resolve()
})
let promise2 = promise.then(res => {
  return new Promise((resolve, reject) => {
    reject('失败')
  })
})
promise2.then(res => {
  console.log(res)
}, err => {
  console.log(err) // 失败
})
复制代码
案例7:x.then成功
let promise = new Promise((resolve, reject) => {
  resolve()
})
let promise2 = promise.then(res => {
  return new Promise((resolve, reject) => {
    resolve(new Promise((resolve, reject) => {
      resolve('成功')
    }))
  })
})
promise2.then(res => {
  console.log(res) // 成功
}, err => {
  console.log(err)
})
复制代码

应用

let fs = require('fs')

function read (filePath, encoding) {
  return new Promise((resolve,reject) => {
    fs.readFile(filePath, encoding, (err, data) => {
      if(err) reject(err)
      resolve(data)
    })
  })
}

read('1.txt', 'utf8').then(res => {
  return read(res, 'utf8')
}).then(res => {
  return read(res, 'utf8')
}).then(res => {
  console.log(res) // hello
})

// 1.txt内容 2.txt
// 2.txt内容 3.txt
// 3.txt内容 hello
复制代码

转载于:https://juejin.im/post/5ce50005e51d4510727c7fe4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值