资讯专栏INFORMATION COLUMN

浅析es6-promise源码

fox_soyoung / 1270人阅读

摘要:主要逻辑本质上还是回调函数那一套。通过的判断完成异步和同步的区分。

主要逻辑:

本质上还是回调函数那一套。
通过_subscribers的判断完成异步和同步的区分。
通过 resolve,reject -> publish -> invokeCallback -> resolve,reject的递归和下一条then的parent是上一条的child来完成then链的流转

同步情况下函数流转: constructor -> resolver -> publish -> then -> invokeCallback
异步情况下函数流转: constructor -> then -> resolver -> publish -> invokeCallback

主要函数解析

1. constructor
作用: 把resolve,reject绑定到 resolver上-

constructor(resolver) {
    this[PROMISE_ID] = nextId();
    this._result = this._state = undefined;
    this._subscribers = [];
    
    if (noop !== resolver) {
      typeof resolver !== "function" && needsResolver();
      
      this instanceof Promise ? initializePromise(this, resolver) : needsNew();
    }
  }

2 then
作用: 把回调函数绑定在_subscribers上,catch和finally本质是then的语法糖
_subscribers的参数是一个数组,[0]是他的child,绑定下一个then链的parent,用于publish递归调用, 第二个是resolve 回调, 第三个是reject回调

export default function then(onFulfillment, onRejection) {
  const parent = this;
  
  const child = new this.constructor(noop);

  if (child[PROMISE_ID] === undefined) {
    makePromise(child);
  }

  const { _state } = parent;
 
  if (_state) {
    const callback = arguments[_state - 1];
    asap(() => invokeCallback(_state, child, callback, parent._result));
  } else {
    subscribe(parent, child, onFulfillment, onRejection);
  }

  return child;
}

3 publish
作用: resolve,reject的触发会调用publish,publish继续调用invokeCallback,通过返回值继续调用resolve,reject,形成一个递归,完成then链的流转

function publish(promise) {
  let subscribers = promise._subscribers;
  let settled = promise._state;

  if (subscribers.length === 0) { return; }

  let child, callback, detail = promise._result;

  for (let i = 0; i < subscribers.length; i += 3) {
    child = subscribers[i];
    callback = subscribers[i + settled];

    if (child) {
      invokeCallback(settled, child, callback, detail);
    } else {
      callback(detail);
    }
  }

  promise._subscribers.length = 0;
}

tip:
finally的callback是没有返回参数的,基于

return promise.then(value => constructor.resolve(callback()).then(() => value),
                         reason => constructor.resolve(callback()).then(() => { throw reason; }));

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102845.html

相关文章

  • es6-promise

    摘要:是什么可以理解为一个承诺,如果调用,返回一个承诺给,然后就可以在写计划的时候这么写,当返回结果的时候,就执行方案,如果没有返回要的结果,就执行方案。这样一来,所有的潜在风险就都在的可控范围之内了。 promise是什么 Promise可以理解为一个承诺,如果A调用B,B返回一个承诺给A,然后A就可以在写计划的时候这么写,当B返回结果的时候,A就执行方案1,如果B没有返回A要的结果,A就...

    jackwang 评论0 收藏0
  • 使用Vue构建中(大)型应用

    摘要:做前端路由管理,一个中大型项目必须要做路由管理做数据管理,类似于的存在,没有,中大型应用中的状态会把开发者搞死,绝对。 想做SPA就快上车! init 首先要起一个项目,推荐用vue-cli安装 $ npm install -g vue-cli $ vue init webpack demo $ cd demo $ npm install demo是这个示例项目的名字 现在看到目录结构...

    Rindia 评论0 收藏0
  • 浅析webpack源码之前言(一)

    为什么读webpack源码 因为前端框架离不开webpack,天天都在用的东西啊,怎能不研究 读源码能学到很多做项目看书学不到的东西,比如说架构,构造函数,es6很边缘的用法,甚至给函数命名也会潜移默化的影响等 想写源码,不看源码怎么行,虽然现在还不知道写什么,就算不写什么,看看别人写的总可以吧 知道世界的广阔,那么多插件,那么多软件开发师,他们在做什么,同样是写js的,怎么他们能这么伟大 好奇...

    suosuopuo 评论0 收藏0
  • 浅析HashMap源码(1)

    摘要:前言本文的目的是阅读理解的源码,作为集合中重要的一个角色,平时用到十分多的一个类,深入理解它,知其所以然很重要。 前言 本文的目的是阅读理解HashMap的源码,作为集合中重要的一个角色,平时用到十分多的一个类,深入理解它,知其所以然很重要。本文基于Jdk1.7,因为Jdk1.8改变了HashMap的数据结构,进行了优化,我们先从基础阅读,之后再阅读理解Jdk1.8的内容 HashMa...

    wwolf 评论0 收藏0
  • 浅析`redux-thunk`中间件源码

    摘要:大多的初学者都会使用中间件来处理异步请求,其理解简单使用方便具体使用可参考官方文档。源码的源码非常简洁,出去空格一共只有行,这行中如果不算上则只有行。官方文档中的一节讲解的非常好,也确实帮我理解了中间件的工作原理,非常推荐阅读。 总觉得文章也应该是有生命力的,欢迎关注我的Github上的博客,这里的文章会依据我本人的见识,逐步更新。 大多redux的初学者都会使用redux-thunk...

    wing324 评论0 收藏0

发表评论

0条评论

fox_soyoung

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<