【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(三、手写Promise源码)

【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(课前准备)

【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(一、函数式编程范式)

【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(二、JavaScript 异步编程)

【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(三、手写Promise源码)

【Part1作业】https://gitee.com/zgp-qz/part01-task

【学习笔记】Part1·JavaScript·深度剖析-ES 新特性与 TypeScript、JS 性能优化(一、ECMAScript 新特性)

【学习笔记】Part1·JavaScript·深度剖析-ES 新特性与 TypeScript、JS 性能优化(二、TypeScript 语言)

【学习笔记】Part1·JavaScript·深度剖析-ES 新特性与 TypeScript、JS 性能优化(三、JavaScript 性能优化1)

【学习笔记】Part1·JavaScript·深度剖析-ES 新特性与 TypeScript、JS 性能优化(四、JavaScript 性能优化2)

【Part2作业】https://gitee.com/zgp-qz/part02-homework

手写Promise源码

Promise 核心逻辑实现

  1. Promise 类核心逻辑实现

  2. 在 Promise 类中加如异步逻辑

  3. 实现 then 方法多次调用,添加多个处理函数

  4. 实现 then 方法的链式调用

  5. then 方法链式调用识别 Promise 对象自返回

  6. 捕获错误以及 then 链式调用其他状态码补充

  7. then 方法的参数变为可选参数

  8. Promise.all 方法的实现

  9. Promise.resolve 方法的实现

  10. finally 方法的实现

  11. catch 方法的实现

    首先,要先会用 Promise ,知道怎么用才能知道里面的逻辑该怎么实现:

    - Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
    - Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending
    -- pending -> fulfilled
    -- pending -> rejected
    - resolve和reject函数是用来更改状态的
    -- resolve: fulfilled
    -- reject: rejected
    - then方法内部做的事情就判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调用失败回调函数 then方法是被定义在原型对象中的
    - then成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败后的原因
    - 同一个promise对象下面的then方法是可以被调用多次的
    - then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
    
    // MyPromise.js
    /* 三个状态定义成常量,以后用的时候编辑器会有代码提示 */
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
      constructor (executor) {
        try {
          executor(this.resolve, this.reject)
        } catch (e) {
          this.reject(e);
        }
      }
      // promsie 状态 默认是等待
      status = PENDING;
      // 成功之后的值
      value = undefined;
      // 失败后的原因
      reason = undefined;
      // 成功回调
      successCallback = [];
      // 失败回调
      failCallback = [];
    
      /* 之所以定义成箭头函数,因为调用的时候是直接调用的,如果是一个普通函数 function(){},直接调用的时候内部的 this 对象是 window 或者是 undefined,写成箭头函数让 this 对象指向当前的类  */
      resolve = value => {
        // 如果状态不是等待 阻止程序向下执行,Promise 状态是只有等待的时候才能更改
        if (this.status !== PENDING) return;
        // 将状态更改为成功
        this.status = FULFILLED;
        // 保存成功之后的值
        this.value = value;
        // 判断成功回调是否存在 如果存在 调用
        // this.successCallback && this.successCallback(this.value);
        while(this.successCallback.length) this.successCallback.shift()()
      }
      /* 之所以定义成箭头函数,因为调用的时候是直接调用的,如果是一个普通函数 function(){},直接调用的时候内部的 this 对象是 window 或者是 undefined,写成箭头函数让 this 对象指向当前的类  */
      reject = reason => {
        // 如果状态不是等待 阻止程序向下执行,Promise 状态是只有等待的时候才能更改
        if (this.status !== PENDING) return;
        // 将状态更改为失败
        this.status = REJECTED;
        // 保存失败后的原因
        this.reason = reason;
        // 判断失败回调是否存在 如果存在 调用
        // this.failCallback && this.failCallback(this.reason);
        while(this.failCallback.length) this.failCallback.shift()()
      }
      then (successCallback, failCallback) {
        // 参数可选
        successCallback = successCallback ? successCallback : value => value;
        // 参数可选
        failCallback = failCallback ? failCallback: reason => { throw reason };
        let promsie2 = new MyPromise((resolve, reject) => {
          // 判断状态
          if (this.status === FULFILLED) {
            setTimeout(() => { // 这里为了获取 promise2
              try {
                let x = successCallback(this.value);
                // 判断 x 的值是普通值还是promise对象
                // 如果是普通值 直接调用resolve 
                // 如果是promise对象 查看promsie对象返回的结果 
                // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                resolvePromise(promsie2, x, resolve, reject)
              }catch (e) {
                reject(e);
              }
            }, 0)
          }else if (this.status === REJECTED) {
            setTimeout(() => { // 这里为了获取 promise2
              try {
                let x = failCallback(this.reason);
                // 判断 x 的值是普通值还是promise对象
                // 如果是普通值 直接调用resolve 
                // 如果是promise对象 查看promsie对象返回的结果 
                // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                resolvePromise(promsie2, x, resolve, reject)
              }catch (e) {
                reject(e);
              }
            }, 0)
          } else {
            // 等待
            // 将成功回调和失败回调存储起来
            this.successCallback.push(() => {
              setTimeout(() => {
                try {
                  let x = successCallback(this.value);
                  // 判断 x 的值是普通值还是promise对象
                  // 如果是普通值 直接调用resolve 
                  // 如果是promise对象 查看promsie对象返回的结果 
                  // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                  resolvePromise(promsie2, x, resolve, reject)
                }catch (e) {
                  reject(e);
                }
              }, 0)
            });
            this.failCallback.push(() => {
              setTimeout(() => {
                try {
                  let x = failCallback(this.reason);
                  // 判断 x 的值是普通值还是promise对象
                  // 如果是普通值 直接调用resolve 
                  // 如果是promise对象 查看promsie对象返回的结果 
                  // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                  resolvePromise(promsie2, x, resolve, reject)
                }catch (e) {
                  reject(e);
                }
              }, 0)
            });
          }
        });
        return promsie2;
      }
      finally (callback) {
        return this.then(value => {
          return MyPromise.resolve(callback()).then(() => value);
        }, reason => {
          return MyPromise.resolve(callback()).then(() => { throw reason })
        })
      }
      catch (failCallback) {
        return this.then(undefined, failCallback)
      }
      static all (array) {
        let result = [];
        let index = 0;
        return new MyPromise((resolve, reject) => {
          function addData (key, value) {
            result[key] = value;
            index++;
            if (index === array.length) {
              resolve(result);
            }
          }
          for (let i = 0; i < array.length; i++) {
            let current = array[i];
            if (current instanceof MyPromise) {
              // promise 对象
              current.then(value => addData(i, value), reason => reject(reason))
            }else {
              // 普通值
              addData(i, array[i]);
            }
          }
        })
      }
      static resolve (value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value));
      }
    }
    
    function resolvePromise (promsie2, x, resolve, reject) {
      if (promsie2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
      }
      if (x instanceof MyPromise) {
        // promise 对象
        // x.then(value => resolve(value), reason => reject(reason));
        x.then(resolve, reject);
      } else {
        // 普通值
        resolve(x);
      }
    }
    
    module.exports = MyPromise;
    

【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(课前准备)

【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(一、函数式编程范式)

【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(二、JavaScript 异步编程)

【学习笔记】Part1·JavaScript·深度剖析-函数式编程与 JS 异步编程、手写 Promise(三、手写Promise源码)

【Part1作业】https://gitee.com/zgp-qz/part01-task

【学习笔记】Part1·JavaScript·深度剖析-ES 新特性与 TypeScript、JS 性能优化(一、ECMAScript 新特性)

【学习笔记】Part1·JavaScript·深度剖析-ES 新特性与 TypeScript、JS 性能优化(二、TypeScript 语言)

【学习笔记】Part1·JavaScript·深度剖析-ES 新特性与 TypeScript、JS 性能优化(三、JavaScript 性能优化1)

【学习笔记】Part1·JavaScript·深度剖析-ES 新特性与 TypeScript、JS 性能优化(四、JavaScript 性能优化2)

【Part2作业】https://gitee.com/zgp-qz/part02-homework

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值