「JavaScript」手写promise的实现

知其然必知起所以然

Promise是用来处理异步的一种方案,以前如果在有碰到回调地狱的情况,代码看起来就非常的糟糕,有了promise之后,确实在整体上来说提上了不上,代码间接优美了很多。那么今天就来看一下promise是如何实现。

promise的基本结构

我们都知道promise有三种状态,pending, resolved, rejectd 这三种, 当pending的时候我们并不需要做什么,而resolved执行resolve函数,rejected 执行reject函数

所以可以描述出基本的结构

function Promisex(executor) {
  this.status = 'pending';
  this.value = undefined;
  this.reason = undefined;

  // 当Promise对象已经由pending状态改变为了成功态(resolved)或是失败态(rejected)就不能再次更改状态了
  var resolve = value => {
    // 这个地方说明状态为pending才能更新
    if (this.status === 'pending') {
      this.status = 'resolved';
      this.vaule = value
     }
   }
  var reject = reason => {
  if (this.status === 'pending') {
    this.status = reject
    this.reason = reason
   }
  };
  executor(resolve, reject)

接着再来定义一下then的结构

Promisex.prototype.then = function(onFullFilled, onRejected) {
    if (this.status === 'resolved') {
    onFullFilled(this.value);
} 

   if (this.status === 'rejected') {
      onRejected(this.reason);
}
}

上面可以很容易就展现了一个promise基本的形状

异步解决

你很可能发现上面的函数是同步的吗,如果你异步调用是不起作用的,那么如何解决异步方案--可以通过发布订阅者模式来进行

function Promisex() {
  ```` 省略
  this.onFullFilledFunc = [] // 这里存放成功回调
  this.onRejectedFunc = [] // 这里存放失败回调
}

Promisex.prototype.then = function (onFullFilled, onRejected) {
     // 如果是异步的话,这个地方进来还是pending 状态 
    if (typeof onFullFilled === 'function') {
      this.onFullFilledFunc.push(onFullFilled);
    }

    if (typeof onRejected === 'function') {
      this.onRejectedFunc.push(onRejected);
    }
}

这样就成功处理了promise的静态调用

链式调用

Promise链式调用的核心就把每个结果集再次包裹成一个Promise对象,然后循序调用

所以就可以来一个基本结果样貌

Promisex.prototye.then = function (onFullFilled, onRejected) {
 var promisex1 = new Promsiex( (resolve, reject) => {
    `````` 省略
})
return promisex1
}

如何实现链式调用呢?我们把这个过程抽象成一个函数,来分解

/**
 * 解析then返回值与新Promise对象
 * @param {Object} promise2 新的Promise对象
 * @param {*} x 上一个then的返回值
 * @param {Function} resolve promise2的resolve
 * @param {Function} reject promise2的reject
 */
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    reject(new TypeError('Promise发生循环引用'));
  }

  if (x !== null && (typeof x === 'object' || x === 'function')) {
    // 可能是个对象或者函数
    try {
      let then = x.then;
      if (typeof then === 'function') {
        then.call(
          x,
          y => {
            // resolve(y)
            //递归调用,传入y若是Promise对象,继续循环
            resolvePromise(promise2, y, resolve, reject);
          },
          r => {
            reject(r);
          },
        );
      } else {
        resolve(x);
      }
    } catch (e) {
      reject(e);
    }
  } else {
    resolve(x);
  }
}

具体完整实现过程

function Promisex(executor) {
  this.status = 'pending';
  this.value = undefined;
  this.reason = undefined;
  this.onFullFilledFunc = []; // 保存成功回调状态
  this.onRejectedFunc = []; // 保存失败回调状态

  // 当Promise对象已经由pending状态改变为了成功态(resolved)或是失败态(rejected)就不能再次更改状态了
  var resolve = value => {
    // 这个地方说明状态为pending才能更新
    if (this.status === 'pending') {
      this.value = value;
      this.onFullFilledFunc.forEach(fun => {
        this.value= fun(this.value);
      });
      this.status = 'resolved';
    }
  };

  var reject = reason => {
    if (this.status === 'pending') {
      this.onRejectedFunc.forEach(fun => fun(reason));
      this.reason = reason;
      this.status = 'rejected'
    }
  };

  executor(resolve, reject);
}

Promisex.prototype.then = function(onFullFilled, onRejected) {
  if (this.status === 'pending') {
    if (typeof onFullFilled === 'function') {
      this.onFullFilledFunc.push(onFullFilled);
    }

    if (typeof onRejected === 'function') {
      this.onRejectedFunc.push(onRejected);
    }
    return this;
  }
  var promise2 = new Promisex((resolve, reject) => {
    if (this.status === 'resolved') {
      setTimeout(() => {
        try {
          let x = onFullFilled(this.value);
          resolvePromise(promise2, x, resolve, reject);
        } catch (e) {
          reject(e);
        }
      }, 0);
    }
    if (this.status === 'rejected') {
      onRejected(this.reason);
    }
  });
  return promise2;
};

/**
 * 解析then返回值与新Promise对象
 * @param {Object} promise2 新的Promise对象
 * @param {*} x 上一个then的返回值
 * @param {Function} resolve promise2的resolve
 * @param {Function} reject promise2的reject
 */
function resolvePromise(promise2, x, resolve, reject) {
  if (promise2 === x) {
    reject(new TypeError('Promise发生循环引用'));
  }

  if (x !== null && (typeof x === 'object' || x === 'function')) {
    // 可能是个对象或者函数
    try {
      let then = x.then;
      if (typeof then === 'function') {
        then.call(
          x,
          y => {
            // resolve(y)
            //递归调用,传入y若是Promise对象,继续循环
            resolvePromise(promise2, y, resolve, reject);
          },
          r => {
            reject(r);
          },
        );
      } else {
        resolve(x);
      }
    } catch (e) {
      reject(e);
    }
  } else {
    resolve(x);
  }
}

module.exports = Promisex;
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Promise 对象 Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函...
    neromous阅读 8,735评论 1 56
  • 目录:Promise 的含义基本用法Promise.prototype.then()Promise.prototy...
    BluesCurry阅读 1,503评论 0 8
  • 关于Promise的基本内容,已经写过一篇文章。基本的会用,偶尔也用过,不过知识点比较多,并且代码在外面套了好几层...
    松哥888阅读 1,146评论 0 4
  • 原文地址:http://es6.ruanyifeng.com/#docs/promise Promise 的含义 ...
    AI云栈阅读 903评论 0 7
  • 有铁骨铮铮 也有柔情似水 1 柳树,是很常见的树种,也是遭受误会很深的树种。 俗语有,房屋“前不栽杨,后不栽柳”的...
    flyinrain12123阅读 680评论 0 1