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模拟

const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";

// 决定then返回的promise的状态
function resolvePromise(x, promise2, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError('循环引用'))
  }

  if (typeof x === 'object' && x !== null || typeof x === 'function') {
    let called;
    try {
      let then = x.then; // 是promise,含有then方法
      if (typeof then === 'function') {
        // x是promise
        // 需要使用call修改this指向x   promise   避免再次从x上取值
        then.call(x, (value) => {
          // fulfilled
          if (called) return;
          called = true;
          resolvePromise(value, promise2, resolve, reject)
        }, (error) => {
          // rejected
          if (called) return;
          called = true;
          reject(error)
        })
      } else {
        resolve(x)
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e)
    }
  } else {
    // 普通值直接resolve  没有返回值,undefined也走这里
    resolve(x)
  }
}

class Promise {
  constructor(executor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;

    this.onResolveCallbacks = []
    this.onRejectCallbacks = []

    const resolve = (value) => {
      // 场景: resolve(promise)
      if (value instanceof Promise) {
        return value.then(resolve, reject)
      }
      if (this.status === PENDING) {
        this.status = FULFILLED
        this.value = value
        this.onResolveCallbacks.forEach(fn => fn())
      }
    }

    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED
        this.reason = reason
        this.onRejectCallbacks.forEach(fn => fn())
      }
    }

    try {
      executor(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onFulfilled, onRejected) {
    // 场景:
    // new Promise((resolve, reject) => {
    //   resolve(1)
    // })
    // .then().then((data) => {
    //   console.log(data)
    // })
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (data) {
      return data
    }
    onRejected = typeof onRejected === 'function' ? onRejected : err => {
      throw err
    }
    // then返回一个新的promise
    let promise2 = new Promise((resolve, reject) => {
      // 处理异步
      if (this.status === PENDING) {
        this.onResolveCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value)
              resolvePromise(x, promise2, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
        this.onRejectCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason)
              resolvePromise(x, promise2, resolve, reject)
            } catch (e) {
              reject(e)
            }
          }, 0)
        })
      }

      // 同步情况,直接处理,不需要放入队列
      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value)
            resolvePromise(x, promise2, resolve, reject)
          } catch (e) {
            reject(e)
          }
        }, 0)
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason)
            resolvePromise(x, promise2, resolve, reject)
          } catch (e) {
            reject(e)
          }
        })
      }
    })

    return promise2
  }

  catch (errCallback) {
    return this.then(null, errCallback)
  }

  static resolve(value) {
    return new Promise((resolve) => {
      resolve(value)
    })
  }

  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason)
    })
  }

  static all(promises) {
    return new Promise((resolve, reject) => {
      let times = 0;
      const arr = []

      function processMap(key, value) {
        arr[key] = value;
        if (++times === promises.length) {
          resolve(arr)
        }
      }
      for (let i = 0; i < promises.length; i++) {
        let promise = promises[i]; // 可能是普通值,也可能是promise
        let then = promise && promise.then
        if (typeof then === 'function') {
          then.call(promise, (data) => {
            processMap(i, data)
          }, reject)
        } else {
          processMap(i, promise)
        }
      }
    })
  }
  
  // finally返回的promise的状态取决于调用它的promise的状态(xxx.finally())
  finally(cb) {
    return this.then((y) => {
      return Promise.resolve(cb()).then(() => y, (err) => {
        throw err
      })
    }, (err) => {
      return Promise.resolve(cb()).then(() => {
        throw err
      })
    })
  }

  static race(values) {
    return new Promise((resolve, reject) => {
      for (let i = 0; i < values.length; i++) {
        let p = values[i]
        // 原生的promise,如果里面放的是一个promise,会进行优化,不会再进行包装  1次then
        // 自己写的promise,如果当前resolve里面放的是promise,会调用这个promise.then  2次then
        Promise.resolve(p).then(resolve, reject)
      }
    })
  }
}

Promise.deferred = function () {
  let dfd = {}
  dfd.promise = new Promise((resolve, reject) => {
    dfd.resolve = resolve;
    dfd.reject = reject
  })
  return dfd
}

// deferred  延迟对象  目的是产生一个可以延迟的promise对象
function readFile(...args) {
  let dfd = Promise.deferred();
  fs.readFile(...args, function (err, data) {
    if (err) return dfd.reject(err)
    dfd.resolve(data)
  })
  return dfd.promise
}

module.exports = Promise
``
  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:28:16 
 
开发: 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:36:47-

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