专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

前端ES6中Promise的运行原理之进阶篇(一)

ins518 2024-09-24 18:16:24 技术文章 15 ℃ 0 评论

在上一篇前端ES6中Promise的运行原理的讲解中其实有很多细节方面没有提及到,这篇我们讨论更细致一点。

回顾上一篇重点

这个图就代表上一篇说到的链式调用,而链式调用的开关就是Promise里面的resolve方法。

一种数据流的实现方式

在js中有很多种形式的数据流,比如常用的事件回调、express中的next方法,类似于koa的洋葱皮,包括Promise本身也是一种数据流形式!Promise内部实现了一种数据流来支撑Promise的运转。

首先我们来看一个遍历函数flush,很容易看出来它的遍历速度是2,因为每一次的遍历都需要从queue数组中拿出一个方法callback和一个参数arg,然后把他们放在一起执行,但是它们又怎么形成一个数据流的呢?关键就在于这个len,queue 和这个callback。

  1. 首先向queue中push一对callback和arg,此时len==2
  2. 这是flush中的遍历就能运行起来,开始遍历,从queue中取出callback和arg,开始执行callback(arg)
  3. 在执行callback的过程中,又向queue中push一个callback和一个arg,此时len变成了4
  4. 那么flush中的for循环在遍历一遍后本来是要终止的,但是callback把len变成了4,又可以继续往下遍历queue
  5. 依次类推,就实现了一个数据流

向queue中添加数据的操作可以处理成一个单独的方法asap

可以看出来,asap只是在第一次触发了flush,后面就可以像流水一样自己能自行流动。这个async方法名是我编造的,不要把它理解为保留字,只是为了便于理解,代表一个异步的方法,它可能的值有下面几个:

  • setTimeout
  • process.nextTick
  • MutationObserver
  • vertxNext
  • MessageChannel
  • 自定义

这些都有可能,完全看运行环境的兼容性如何。

数据流运用到Promise中

我们先看一下上一篇中的一个demo

p1的运行是同步完成的,所以p2可以直接拿到p1的状态和结果,那么我们结合上一篇文章重构一下then方法。

拿到上一个promise状态的then可以直接通过asap去触发flush,这里定义了一个invokeCallback方法,猜测一下它里面做了什么?其实很简单:

在flush中运行了invokeCallback,修改child的状态和结果,child又会继续运行下一个promise对象。上图中的红色区域中的代码可以提取出来,再通过asap传入queue中通过flush执行。

还有一个问题:不是每个then都能同步拿到上一个Promise的状态和结果,那这种情况下就是我们之前说的把child挂在到parent上,等待上面的promise状态修改完成会自动遍历到下面的child,重构一下then方法:

总结

说到这里,promise数据流的形成过程已经说的差不多了!下一篇我们再研究一下promise处理过程中的几种特殊情况!

喜欢我的文章就关注我吧,有问题可以发表评论,我们一起学习,共同成长!(别只顾着收藏和转发,关注一下吧,你们的关注是我的动力!)

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表