前言   

DAG是有向无环图(Directed Acyclic Graph)的简称。在大数据处理中,DAG计算常常指的是将计算任务在内部分解成为若干个子任务,将这些子任务之间的逻辑关系或顺序构建成DAG(有向无环图)结构。

前端组件对比 javascript实现 前端dag组件_前端组件对比 javascript实现

X6在DAG图中的实践

X6 是一款开源的图编辑引擎,vue3.x+vite2.x是目前较火的前端开发组合,现在用他们来实现一个DAG图;

X6分为画布(Graph)、基类(cell)、节点(node)、边(edge)、连接桩(port)等元素,以及图的相关操作(如交互监听、元素操作、渲染等),因此只需要掌握画布、节点、边的增删改查,使用x6就轻松加愉快了。

基于x6封装一个类GraphCroe

前端组件对比 javascript实现 前端dag组件_有向无环图_02

使用vue组件注册x6自定义节点

前端组件对比 javascript实现 前端dag组件_前端组件对比 javascript实现_03

注册x6自定义边 

前端组件对比 javascript实现 前端dag组件_大数据_04

在GraphCore类中添加节点,边的操作方法

前端组件对比 javascript实现 前端dag组件_大数据_05

在vue组件中创建画布

前端组件对比 javascript实现 前端dag组件_有向无环图_06

提供创建节点数据方法

前端组件对比 javascript实现 前端dag组件_连线_07

以上步骤就可以实现在画布中创建节点的功能,如下图: 

前端组件对比 javascript实现 前端dag组件_前端组件对比 javascript实现_08

要做一个有向无环图还需要解决以下2个问题:

  1. 有方向,连线只能从上一个节点的输出桩(下面)连接到当前节点的输入桩(上面);
  2. 无环,输出桩发起的连线不能成环,即当前节点不能连接自己,不能连接自己上面所有连接过的节点。

综合以上问题只要在 defaultConfig 中配置连线校验逻辑即可:

前端组件对比 javascript实现 前端dag组件_有向无环图_09

至此,一个简单的DAG图就已经完成了。

进阶

学过计算机网络的知道计算机网络中有一个拓扑结构,要实现 DAG图多顶点的拓扑序列执行任务的功能,可以使用拓扑排序算法,拓扑排序算法的时间复杂度为O(n+e)。

前端组件对比 javascript实现 前端dag组件_有向无环图_10

Js实现拓扑排序算法

前端组件对比 javascript实现 前端dag组件_拓扑排序_11

笔者在这里提供了另一种思路:

把每一个节点看作一个对象,因此只要关心两件事就可以解决DAG图多顶点的拓扑结构执行任务的功能。

  1. 遍历每个节点,把它放到事件订阅里边,执行订阅器;
  2. 每隔一秒检查一下,如果当前节点已经在运行,则跳过;当前节点是否有上级节点,没有就是顶点节点,顶点直接运行;有上级节点,上级节点是否有运行结果,所有上级节点都有运行结果就运行当前节点;当前节点有运行结果,从订阅器里删除当前节点;当前节点运行报错,从订阅器里删除当前节点;上级节点有报错,删除当前节点;最后订阅器里就空了,所有的任务也就执行完了。 

前端组件对比 javascript实现 前端dag组件_前端组件对比 javascript实现_12

前车之鉴

在vue3.x+vite2.x中使用x6必然是要趟过很多坑的,下面是开发过程中遇到的一些问题:

1.使用 "@antv/x6-vue-shape"来注册vue组件,需要vue在运行时进行编译,在vite别名中添加 

前端组件对比 javascript实现 前端dag组件_连线_13

2.开发阶段@antv/x6,@antv/x6-vue-shape 引入报错,开发阶段修改别名

前端组件对比 javascript实现 前端dag组件_连线_14

小结

本文由浅入深介绍了DAG图基于X6实现,以及拓展了解决DAG图多顶点的拓扑结构执行任务的另外一种思路,相信你已经很清楚地知道怎么实现一个DAG图了。

感谢阅读,如有不足之处,欢迎指出。

end