hgq's docs
主页
ES6-阮一峰 (opens new window)
Vue文档 (opens new window)
Axios文档 (opens new window)
Vue Router (opens new window)
Vuex文档 (opens new window)
面试题-Vue (opens new window)
面试题-JS (opens new window)

guoguoqiqi

漫不经心的向往
主页
ES6-阮一峰 (opens new window)
Vue文档 (opens new window)
Axios文档 (opens new window)
Vue Router (opens new window)
Vuex文档 (opens new window)
面试题-Vue (opens new window)
面试题-JS (opens new window)
  • JS数据类型
  • JS数据类型的转换
  • 判断数据类型的方法
  • null和undefined的区别
  • parseInt方法解析
  • promise简答
  • var和let以及const的区别
  • 本地存储的几种方式
  • 闭包是什么
  • 调用new的过程
  • 防抖和节流
  • 简单讲讲异步的理解
  • 简单讲讲原型和原型链
  • 判断变量的数据类型
  • 深浅拷贝
  • 数组去重的方法
  • 说一说JS中的this
  • 作用域和作用域链
  • JS的内置对象
  • JS继承的几种实现方式
  • 谈谈你对this、call、apply和bind的理解
  • 说一说原型、原型链
  • 什么是闭包,为什么使用闭包
  • JS中事件冒泡与捕获
  • 说一说JS的事件模型
  • 常用的遍历数组的方法
  • 如何创建一个Ajax
  • js 延迟加载的方式有哪些
  • 谈谈你对模块化开发的理解
  • js 的几种模块规范
  • ES6 模块与 CommonJS 模块、AMD、CMD 的差异
  • JS的运行机制、单线程、事件循环、宏任务微任务
  • arguments 的对象是什么
  • 简单介绍一下 V8 引擎的垃圾回收机制
  • 哪些操作会造成内存泄漏
  • ES6有哪些新特性
  • 说一说箭头函数
  • 什么是高阶函数
  • 为什么函数被称为一等公民
  • js的深浅拷贝
  • 函数柯里化
  • 说一说new操作符
  • 说一说对Promise的理解
  • Generator函数是什么,有什么作用
  • 说一说async和await
  • instanceof的原理是什么,如何实现
  • js 的节流与防抖
  • 相关面试题集合
  • 如何更好的处理async、await的异常
  • JS的事件委托
  • 浏览器和node中事件循环的区别
  • mouseover 和 mouseenter 的区别
  • ===与Object is的区别
  • 数组去重有哪些方法
  • 页面在浏览器中渲染出来的原理和流程
  • js和css是否会阻塞页面的渲染
  • Set、Map、WeakSet 和 WeakMap 的区别
  • 说一说Promise的实现原理
    • 说一说JS的事件循环
    • == 和 === 与隐式转化
    • 说一说回流(重排)和重绘
    • script标签中添加async或defer的作用与区别
    • 如何中断一个请求
    • 遍历一个对象身上属性的方法有哪些
    • 常用的数组方法(不改变原数组)
    • 常用的数组方法(改变原数组)
    • 常用字符串操作方法
    • 对象身上与原型相关的方法
    • 数组的reduce方法
    • 常用的位运算符有哪些
    • 浮点数运算有误差的问题
    • typeof和instanceof的区别
    • 有关js和css对页面渲染阻塞的问题
    • 说说对闭包的理解
    • DOMContentLoaded方法
    • es6中对象新增的方法
    • es6中数组新增的方法
    • es6中字符串新增的方法
    • es6新增的Reflect
    • 如何判断一个变量是否是数组
    • onload 和 DOMContentLoaded的区别
    • 大文件上传问题
    • 上传、下载和普通请求的区别
    • Javascript
    guoguoqiqi
    2022-02-22

    说一说Promise的实现原理

    # 上代码

    class Promise {
      constructor(params) {
        //初始化state为pending
        this.state = 'pending';
        //成功的值,返回一般都是undefined
        this.value = undefined;
        //失败的原因,返回一般都是undefined
        this.reason = undefined;
        //成功执行函数队列
        this.onResolvedCallbacks = [];
        //失败执行函数队列
        this.onRejectedCallbacks = [];
    
        //success
        let resolve = value => {
          if (this.state === 'pending') {
            //state change
            this.state = 'fulfilled';
            //储存成功的值
            this.value = value;
            //一旦成功,调用函数队列
            this.onResolvedCallbacks.forEach(fn => fn());
          }
        };
    
        //error
        let reject = reason => {
          if (this.state === 'pending') {
            //state change
            this.state = 'rejected';
            //储存成功的原因
            this.reason = reason;
            //一旦失败,调用函数队列
            this.onRejectedCallbacks.forEach(fn => fn());
          }
        };
        try {
          params(resolve, reject);
        } catch (err) {
          reject(err);
        }
      }
      then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : err => {
          throw err
        };
        let promise2 = new Promise((resolve, reject) => {
          //当状态是fulfilled时执行onFulfilled函数
          if (this.state === 'fulfilled') {
            //异步实现
            setTimeout(() => {
              try {
                let x = onFulfilled(this.value);
                resolvePromise(promise2, x, resolve, reject);
              } catch (e) {
                reject(e);
              }
            }, 0);
          };
          //当状态是rejected时执行onRejected函数
          if (this.state === 'rejected') {
            //异步实现
            setTimeout(() => {
              try {
                let x = onRejected(this.reason);
                resolvePromise(promise2, x, resolve, reject);
              } catch (e) {
                reject(e);
              }
            }, 0);
          };
          //当状态是pending时,往onFulfilledCacks、onRejectedCacks里加入函数
          if (this.state === 'pending') {
            this.onResolvedCallbacks.push(() => {
              //异步实现
              setTimeout(() => {
                try {
                  let x = onFulfilled(this.value);
                  resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                  reject(e);
                }
              }, 0);
            });
            this.onRejectedCallbacks.push(() => {
              //异步实现
              setTimeout(() => {
                try {
                  let x = onRejected(this.reason);
                  resolvePromise(promise2, x, resolve, reject);
                } catch (e) {
                  reject(e);
                }
              }, 0)
            });
          };
        });
        return promise2;
      }
      catch(fn) {
        return this.then(null, fn);
      }
    }
    
    function resolvePromise(promise2, x, resolve, reject) {
      //循环引用报错
      if (x === promise2) {
        return reject(new TypeError('Chaining cycle detected for promise'));
      }
      //防止多次调用
      let called;
      //判断x
      if (x != null && (typeof x === 'object' || typeof x === 'function')) {
        try {
          let then = x.then;
          if (typeof then === 'function') {
            then.call(x, y => {
              if (called) return;
              called = true;
              resolvePromise(promise2, y, resolve, reject);
            }, err => {
              if (called) return;
              called = true;
              reject(err);
            })
          } else {
            resolve(x);
          }
        } catch (e) {
          if (called) return;
          called = true;
          reject(e);
        }
      } else {
        resolve(x);
      }
    }
    //resolve方法
    Promise.resolve = function (val) {
      return new Promise((resolve, reject) => {
        resolve(val)
      });
    }
    //reject方法
    Promise.reject = function (val) {
      return new Promise((resolve, reject) => {
        reject(val);
      });
    }
    
    const test = new Promise((res, rej) => {
      setTimeout(() => {
        res('resolve after 2000ms');
      }, 2000)
    })
    
    test.then(res => {
      console.error('res: ', res);	// res: resolve after 2000ms
    })
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161

    # 参考文章链接

    手把手一行一行代码教你“手写Promise“,完美通过 Promises/A+ 官方872个测试用例 (opens new window)
    Promise不会??看这里!!!史上最通俗易懂的Promise!!! (opens new window)

    ← Set、Map、WeakSet 和 WeakMap 的区别 说一说JS的事件循环→

    最近更新
    01
    vuex数据持久化怎么做
    05-22
    02
    vue的动态路由怎么配置使用
    05-22
    03
    vue权限控制一般怎么做
    05-22
    更多文章>
    Theme by Vdoing | Copyright © 2022-2022 Guoquoqiqi | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式