轻松管理前端业务中繁琐的流程控制

525 阅读4分钟

前言

很多做业务开发的小伙伴或多或少的会遇到复杂的业务流程的流转

举个例子:

流程控制示意图.png

哇哦,看起来好乱哦~(无鼠标绘制,凑合看吧)

像类似这种的流程控制图,随着业务的不断迭代,细化分支不断地增加,我们的代码会逐渐变得繁琐且难以维护。

没错,我现在就面临这样的困境,随着客户间差异存在,流程中部分相同部分又有差异,想要复用逻辑又无从下手,没办法,只能另辟蹊径,推倒重来!

思考

1.流程拆解

要解决这种繁琐的流程控制及其分支,首先需要将每一个流程的分支单元独立,然后在进行自由组合,来应对不同客户间的差异以及最大程度的复用历史代码逻辑

这里我先尝试对上述流程进行拆解,将每个子节点作为一个原子进行存储,然后交给有限状态自动机来进行调度,以此来实现一个简单的流程控制原型。

代码实现如下展示:

大家可以点击运行观察一下控制台的输入内容,是否基本符合上面流程图中的描述。

到这里,大家应该已经了解流程控制基本代码原理了,其实就是通过递归调用的方式,来完成每个流程分支的状态流转。

那么,新的问题就来了,上面的代码的确可以执行,但是,如果我希望可以有一个执行栈来管理这些原子流程节点,该怎么做呢?

2.流程管理

我们对代码进行小小的改造: 增加一个 actions 来管理原子事件,可以根据场景的不同任意调整待执行的任务。 栈有了,那么耦合在 Map 中的 resolve 该怎么处理呢?

我们需要使用一个指针 point,需要流程走下一步的时候,可以移动这根指针,来获取到下一节点的 action,当然不止这一种方法,大家可以集思广益。

代码实现如下展示:

3.参数传递

上面两步基本上满足了我们的事件原子化和流程编排控制,但是实际应用场景下,很可能存在业务参数传递的过程,那么我们如何将上下文 context 注入到整个流程中呢?

可以尝试利用闭包来动态生成整个 ProcessActionMap,通过一个 exec 函数收集参数的同时,启动整个流程装置。

由于闭包作用域的特殊性,可以让每一个 ProcessActionMap 中的 action 都可以访问到 context 上下文,这样就完成了参数的传递。

代码实现如下展示:

4.流程管理的进一步优化

上面代码中控制指针移动的方式,我们可以考虑封装为一个 next 函数,回到起点也封装为一个 retry 函数,通过函数参数的方式提供给 Action 使用,简化代码调用。

需要对 createMap 进行改造,除了定义 next、retry 函数之外,我们还需要将原本的事件 map 进一步独立出来,方便业务层面在单独的 js 中实现和改写,也为了方便后续我们封装抽象工具类。

代码实现如下展示:

5.封装抽象工具类

上面我们通过4个步骤进行拆解,逐步完善了我们的流程控制器,那么实际业务中肯定是不能写这么一大堆代码的,除了 ProcessActionMap 需要业务层面具体实现外,我们流程控制器可以抽象为一个独立的 class StatusMerchain 进行流程的生成和启动,降低业务层面使用难度。

代码整理后,如下展示:

总结

前端业务中很多流程控制逻辑,想要提高代码的重复利用率,就得考虑功能原子化与功能编排,那么就需要有相应的工具引擎来支持流程调度,这里浅浅和大家分享一下自己对这方面的思考,希望可以通过评论区交流找到更优的解决方案。