IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 手写 Promise -> 正文阅读

[JavaScript知识库]手写 Promise

手写 Promise

需要实现的功能

  • 初始化 & 异步调用

    // Promise 的参数是个函数,函数里有两个参数,一个是成功回调,一个是失败回调
    const p1 = new Promise((resolve, reject) => {
      resolve(100)
      // 也支持异步
      // setTimeout(() => {
      //   resolve(100)
      // }, 500)
    })
    
  • then、catch 链式调用

    p.then((data) => {
      return data + 1
    }).then((data) => {
      return data + 2
    }).catch((err) => {
      console.log(err)
    })
    
    // then 也可以传入两个参数
    // 一个是成功后的回调,一个是失败后的回调
    p.then(fn1, fn2)
    
    // 链式调用本质是每次调用返回一个新的 promise
    const p11 = p1.then((data) => {
      return data + 1
    })
    const p12 = p11.then((data) => {
      return data + 2
    })
    const p13 = p12.catch((err) => {
      console.log(err)
    })
    
  • API .resolve .reject .all .race

    // 创建一个 resolved 状态的 promise 并附带成功信息
    const p2 = Promise.resolve(200)
    // 创建一个 rejected 状态的 promise,并附带 rejected 的原因
    const p3 = Promise.reject("错误信息...")
    // 当所有 promise 都 resolved 后返回数组结果。
    // 如果有 rejected 则返回 rejected 状态的 promise 并说明错误原因
    const p4 = Promise.all([p1, p2])
    // 哪个 promise 先执行完就直接返回,不管是 resolved 或 rejected
    const p5 = Promise.race([p1, p2])
    

1. 构造函数

class MyPromise {
  constructor (fn) {
    this.state = 'pending' // 状态,'pending' 'resolved', 'rejected
    this.value = undefined // 成功后的值
    this.reason = undefined // 失败后的原因

    this.resolveCallbacks = []; // pending 状态下,存储成功的回调
    this.rejectCallbacks = []; // pending 状态下,存储失败的回调

    const resolveHandler = (value) => {
      if (this.state === 'pending') {
        this.state = 'resolved'
        this.value = value
        // 状态变化后,执行存储的回调方法
        this.resolveCallbacks.forEach(fn => fn(this.value))
      }
    }
    const rejectHandler = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.reason = reason
        this.rejectCallbacks.forEach(fn => fn(this.reason))
      }
    }
    
    try {
      fn(resolveHandler, rejectHandler)
    } catch (err) {
      rejectHandler(err)
    }
  }

  then(fn1, fn2) {
    // 当 pending 状态下,fn1 fn2 会被存储到 callback 中
  }
    
  // 就是 then 的一个语法糖,简单模式
  catch(fn) {
    return this.then(null, fn)
  }
}

2. then 的链式调用

class MyPromise {
  constructor (fn) {
    this.state = 'pending' // 状态,'pending' 'resolved', 'rejected
    this.value = undefined // 成功后的值
    this.reason = undefined // 失败后的原因

    this.resolveCallbacks = []; // pending 状态下,存储成功的回调
    this.rejectCallbacks = []; // pending 状态下,存储失败的回调

    const resolveHandler = (value) => {
      if (this.state === 'pending') {
        this.state = 'resolved'
        this.value = value
        this.resolveCallbacks.forEach(fn => fn(this.value))
      }
    }
    const rejectHandler = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.reason = reason
        this.resolveCallbacks.forEach(fn => fn(this.reason))
      }
    }

    try {
      fn(resolveHandler, rejectHandler)
    } catch (error) {
      rejectHandler(err)
    }
  }

  then(fn1, fn2) {
    // 当 pending 状态下,fn1 fn2 会被存储到 callback 中
    fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
    fn2 = typeof fn2 === 'function' ? fn2 : (v) => v

    if (this.state === 'pending') {
      return new MyPromise((resolve, reject) => {
        // push 进去的函数得等状态为 resolved 的时候才会被执行
        this.resolveCallbacks.push(() => { 
          try {
            const newValue = fn1(this.value);
            resolve(newValue)
          } catch (err) {
            reject(err)
          }
         })

        // push 进去的函数得等状态为 rejected 的时候才会被执行
        this.resolveCallbacks.push(() => { 
          try {
            const newReason = fn2(this.reason);
            reject(newReason )
          } catch (err) {
            reject(err)
          }
         })
      })
    }

    // const p11 = p1.then((data) => {
    //   return data + 1
    // })
    if (this.state === 'resolved') {
      return new MyPromise((resolve, reject) => {
        try {
          // 传入 resolved 的返回值
          const newValue = fn1(this.value)
          resolve(newValue)
        } catch (error) {
          reject(error)
        }
      })
    }

    if (this.state === 'rejected') {
      return new MyPromise((resolve, reject) => {
        try {
          // 传入 rejected 的原因
          const newReason = fn2(this.reason)
          reject(newReason)
        } catch (error) {
          reject(error)
        }
      })
    }
  }
    
  // 就是 then 的一个语法糖,简单模式
  catch(fn) {
    return this.then(null, fn)
  }
}

3. Promise-all 和 race

class MyPromise {
  constructor (fn) {
    this.state = 'pending' // 状态,'pending' 'resolved', 'rejected
    this.value = undefined // 成功后的值
    this.reason = undefined // 失败后的原因

    this.resolveCallbacks = []; // pending 状态下,存储成功的回调
    this.rejectCallbacks = []; // pending 状态下,存储失败的回调

    const resolveHandler = (value) => {
      if (this.state === 'pending') {
        this.state = 'resolved'
        this.value = value
        this.resolveCallbacks.forEach(fn => fn(this.value))
      }
    }
    const rejectHandler = (reason) => {
      if (this.state === 'pending') {
        this.state = 'rejected'
        this.reason = reason
        this.resolveCallbacks.forEach(fn => fn(this.reason))
      }
    }

    try {
      fn(resolveHandler, rejectHandler)
    } catch (error) {
      rejectHandler(error)
    }
  }

  then(fn1, fn2) {
    // 当 pending 状态下,fn1 fn2 会被存储到 callback 中
    fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
    fn2 = typeof fn2 === 'function' ? fn2 : (v) => v

    if (this.state === 'pending') {
      return new MyPromise((resolve, reject) => {
        // push 进去的函数得等状态为 resolved 的时候才会被执行
        this.resolveCallbacks.push(() => { 
          try {
            const newValue = fn1(this.value);
            resolve(newValue)
          } catch (error) {
            reject(error)
          }
         })

        // push 进去的函数得等状态为 rejected 的时候才会被执行
        this.resolveCallbacks.push(() => { 
          try {
            const newReason = fn2(this.reason);
            reject(newReason)
          } catch (error) {
            reject(error)
          }
         })
      })
    }

    // const p11 = p1.then((data) => {
    //   return data + 1
    // })
    if (this.state === 'resolved') {
      return new MyPromise((resolve, reject) => {
        try {
          // 传入 resolved 的返回值
          const newValue = fn1(this.value)
          resolve(newValue)
        } catch (error) {
          reject(error)
        }
      })
    }

    if (this.state === 'rejected') {
      return new MyPromise((resolve, reject) => {
        try {
          // 传入 rejected 的原因
          const newReason = fn2(this.reason)
          reject(newReason)
        } catch (error) {
          reject(error)
        }
      })
    }
  }
    
  // 就是 then 的一个语法糖,简单模式
  catch(fn) {
    return this.then(null, fn)
  }
}

// 全局静态 API
MyPromise.resolve = function(value) {
  return new MyPromise((resolve, reject) => resolve(value))
}

MyPromise.reject = function(reason) {
  return new MyPromise((resolve, reject) => reject(reason))
}

MyPromise.all = function (promiseList = []) {
  const p1 = new MyPromise((resolve, reject) => {
    const result = [] // 存储 promiseList 所有的结果
    const length = promiseList.length
    
    let resolvedCount = 0
    promiseList.forEach((p) => {
      p.then(data => {
        result.push(data)
        // resolvedCount 必须在 then 里面做 ++ (then 执行,累加才算数)
        // 不能用 index,因为 promise 里是异步的,index 递增是同步的
        resolvedCount++
        if (resolvedCount === length) {
          // 已经遍历到了最后一个 promise,把数据 resolve 出去
          resolve(result)
        }
      }).catch(err => {
        reject(err)
      })
    })
  })
  return p1
}

MyPromise.race = function (promiseList = []) {
  let resolved = false
  const p1 = new MyPromise((resolve, reject) => {
    promiseList.forEach(p => {
      p.then(data => {
        if (!resolved) {
          resolve(data)
          resolved = true
        }
      }).catch((err) => {
        reject(err)
      })
    })
  })
  return p1
}
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-24 00:26:06  更:2022-03-24 00:30:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:41:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码