加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_扬州站长网 (https://www.0514zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > Asp教程 > 正文

Bluebird源码分析

发布时间:2022-11-25 14:47:06 所属栏目:Asp教程 来源:
导读:  Promise作为处理异步事件的组件,现在已经是广泛使用了,但是估计很多人还是不了解它的原理。笔者在这里给大家做个分析,希望能让大家对Promise有个更深入的了解。

  笔者是使用bluebird 2.11版来做源码分
  Promise作为处理异步事件的组件,现在已经是广泛使用了,但是估计很多人还是不了解它的原理。笔者在这里给大家做个分析,希望能让大家对Promise有个更深入的了解。
 
  笔者是使用bluebird 2.11版来做源码分析。
 
  先来个简单的使用Promise代码。
 
  function abc() {
      return 'ttt';
  }
  function bcd(kk) {
      console.log(kk + "uuuu");
  }
  Promise.resolve()
      .then(abc)
      .then(bcd)
      .catch(function(error) {
          console.log('the first: ' +error);
      });
  console.log("the last");
  输出结果这里就不做解释了。
 
  当代码执行到Promise.resolve(),发生了什么呢?
 
  在Chrome浏览器上调试发现,进入了Promise的类函数Promise.cast
 
  返回了一个ret(称为firstRet),firstRet是一个Promise对象,可以看到几个关键属性都是undefined。应该说是返回一个空的Promise对象。大家可能疑惑为什么是Promise.cast函数。其实是这行代码
 
  Promise.resolve = Promise.fulfilled = Promise.cast;
  然后继续往下走。这个时候原来的Promise代码可以看成下面这个样子。
 
  firstRet.then(abc)
      .then(bcd)
      .catch(function(error) {
          console.log('the first: ' +error);
      });
  现在应该是继续执行then函数,可能这点和大家的认识有区别了。可能很多人认为Promise.resolve()执行后,就到下面的console.log代码了,其实不是的。
 
  继续往下看
 
  从这个代码可以看到参数didFulfill得到了abc这个参数值。其他的参数的值都是undefined。
 
  还有一个很关键的点就是2307行代码。这个this就是刚才第一个的返回值firstRet。然后我们来看_then函数,这个是关键函数。
 
  在_then函数里asp源代码,可以看到
 
  2409行,重新生成了一个新的ret对象(暂时称为secondRet)。
 
   var ret = haveInternalData ? internalData : new Promise(INTERNAL);
  2416行,这行代码是把firstRet把自己传给了target。
 
  var target = this._target();
  然后在2422行,target去挂载_then函数的传入的参数。
 
  可以看到firstRet现在自己的属性变成了这样子。把函数abc挂载到了自己的属性_fulfilmentHandler0上
 
  继续往下看,在2431行,这个也是很关键的一行代码。该行代码调用async对象,传入firstRet对象。Async对象调用AsyncInvoke.call函数,把firstRet放入_normalQueue队列中。

  这个异步对象Async,包含了几个队列,最重要的就是_normalQueue队列。后面会讲到。
 
  这个时候执行完了then函数,最外层的代码变成了
 
  secondRet.then(bcd)
      .catch(function(error) {
          console.log('the first: ' +error);
      });
  继续执行就是
 
  thirdRet.catch(function(error) {
          console.log('the first: ' +error);
      });
  对于catch函数,其实promise源码也是一个_then函数。
 
  当你的catch执行完,代码应该是
 
  fourthRet;
  然后就执行后续的console。
 
  当主线程执行完,现在应该执行Promise的异步线程了。
 
  bluebird会调用drainQueues函数。调试进去。会发现_drainQueue函数里面是一个while循环,循环对象就是_normalQueue。_normalQueue对象的细节这里不展开讨论,数据可以看下面的图。
 
  _drainQueue函数不断循环把队列的Promise对象取出来,通过fn.call调用对象。
 
  可以看到Promise代码被整合成上面的样子。这个是不是很像java里的链表结构。以笔者看来,就是使用链表(ret)和数组(_normalQueue),还有一个setTimeout来实现了Promise的异步处理。
 
  可能读者有个疑惑,怎么最后讲了一个setTimeout,其实笔者留了个坑没填:bluebird如何调用到drianQueues函数?
 
  如果看了文章,并且去调试过的就会知道了。希望评论里有人讲出来。
 

(编辑:应用网_扬州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!