作者:张镇圳
出处:腾云阁
原文:www.qcloud.com/community/article/
537217001491374183(点击文末阅读原文即可前往)
张镇圳,腾讯Web前端高级工程师,对内部系统前端建设有多年经验,喜欢钻研捣鼓各种前端组件和框架。最近一直在想一个问题,如何能让js代码写起来更语义化和更具有可读性。
上周末的时候突发奇想,当代码在运行的时候,其实跟我们做事情是类似的,都是做完一步接着下一步,并且这些事情有些是可规划的,有些是需要做完该步才知道下一步该做什么。想到这里一个js框架雏形在我大脑中慢慢形成,暂且命名为flowJS。
接着说说这个框架应该有哪些API?
1、可以预先规划好流程的每一步,如this.setNext('步骤A').setNext('步骤B')……
2、可以在任何一步决定下一步做什么,如 this.setNext('步骤C'),其实这里的API和上面的一样,只是调用的地方不一样而已。
3、在任何一步中,可以知道当前步是在做什么,前面一步做了什么、下一步准备要做什么,如this.getCurr()、this.getPrev()、this.getNext()。
4、当前步做完后,能将结果告诉下一步(仅仅是下一步能获取到当前步传递的结果,也就是为了保护变量污染,每一步都只能获取到前一步的结果),如 给下一步传值this.nextData({name1:value1,name2:value2,……})、获取上一步传来的值this.stepData(name1)或this.stepData()。
5、可以设置或获取整个流程的全局变量,这样所有的步骤都能共享该变量,如 设置全局变量值this.flowData({name1:value1,name2:value2,……}),获取全局变量值this.flowData(name1)或this.flowData()。
6、上一步可以知道当前步的执行结果,成功 or 失败,如 在上一步中设置this.setNext('步骤B', successFun, failFun)、当前步中通过this.success(args)、this.fail(args)来告诉上一步。
7、当前步可以随时通知下一步开始执行,如this.next()。
8、有些步骤能并行执行,并且要都执行完才能执行下一步,如 this.setNext('步骤A').setNext([步骤B1,步骤B2,步骤B3]).setNext('步骤C')。
9、可以在任何时候知道当前代码流程运行过的轨迹,如flowJS.trace,这对于了解页面的执行过程会比较有帮助。
Talk is cheap, Show me the code!
1、可以预先规划好流程的每一步,如this.setNext('步骤A').setNext('步骤B')……
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO61EicpfF1Q5yBSmB64Jic2r3Q02blefvkFImriaHS1WGIAee8zxX5fx2jw/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6w3y2yoiaI1NzkwECGqC6jicIJvjteic88rqnhfdwrqgc7t4dol8KCyQgg/0?wx_fmt=png)
2、可以在任何一步决定下一步做什么,如 this.setNext('步骤C') ,其实这里的API和上面的一样,只是调用的地方不一样而已。
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6QBIhCrVsRFEzWJeqiaxWy67ibXy2tWBTzuv6BbFL3uBGaicnGtpg5jC5g/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6SyNStXpSBBC5WG6sAicqvicXBLTuIVoFZQRe1xNT7iaZFRcicib1mIpCcXA/0?wx_fmt=png)
3、在任何一步中,可以知道当前步是在做什么,前面一步做了什么、下一步准备要做什么,如 this.getCurr() 、this.getPrev() 、this.getNext() 。
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6WkPlJtF1m6du0sfRichyCtOSvWLVrvz6aqLBE7vwwQPK5nM5RarrucQ/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6BqelfPQmGtuCDQx42ZkJLibrA3gb7Y4rRMxfWMmbG6BGQBicZGwaPnMg/0?wx_fmt=png)
4、当前步做完后,能将结果告诉下一步(仅仅是下一步能获取到当前步传递的结果,也就是为了保护变量污染,每一步都只能获取到前一步的结果),如 给下一步传值this.nextData({name1:value1,name2:value2,……})、获取上一步传来的值this.stepData(name1)或this.stepData()。
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6uQPaxmPMdwEk0oYngpOfY6eJicWyQrBZ1dzJicmrDClqJ6e9ThJrymEA/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6aqPOlWwdP8BogYHOJibgxUxXLvcRBIAc7u5B2K9tJQxxLiaUXQa7Q2Ig/0?wx_fmt=png)
5、可以设置或获取整个流程的全局变量,这样所有的步骤都能共享该变量,如 设置全局变量值this.flowData({name1:value1,name2:value2,……}),获取全局变量值this.flowData(name1)或this.flowData()。
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO62EbwMac7TXNTVTmAq1uQHEaH3BmQibVVTKk0JGcKHKrD0iaO1t8zOpdQ/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6biaLt2rRY7ub6KobEiaiarsicRkIU7hdYiak7mNS8X2JXt9fqV9wVEw3fMg/0?wx_fmt=png)
6、上一步可以知道当前步的执行结果,成功 or 失败,如 在上一步中设置this.setNext('步骤B', successFun, failFun)、当前步中通过this.success(args)、this.fail(args)来告诉上一步。
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6v8sZbqiaVgPdRAwspHJFyyXgoGuf1xdRic2AaXDBiaSWfw5UBgg0QtMCw/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6H84v3ERILgicpGLV2e3Tm4vic9tqE4LBibFU7qKO8Bj0kzja41Egx4w4w/0?wx_fmt=png)
7、当前步可以随时通知下一步开始执行,如this.next()。
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6pcXuRXssPSmXdqPzVznVAN9pfR4Vxc0mnDP5ficDhRWdY14QeZxEwLw/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6PEBC3Vr55QOE1nSbXq8Bobiar0UewicicxBVSmSYzH17YYDkVKM3EnnwQ/0?wx_fmt=png)
8、有些步骤能并行执行,并且要都执行完才能执行下一步,如 this.setNext('步骤A').setNext([步骤B1,步骤B2,步骤B3]).setNext('步骤C')。
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO67UulJRnkjGHjxLWZq0qx2z4uibUVE2rMYELBGibTicgphoKoQVIushFjg/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6MQia404bPLYicQl44xiaAb21RAEiahJdx4xxWkx38LfFjDDQUz0ReslL5g/0?wx_fmt=png)
9、可以在任何时候知道当前代码流程运行过的轨迹,如flowJS.trace,这对于了解页面的执行过程会比较有帮助。
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6chyr3ib7qPXJmPibaFNA08O2hofP1Nzgo1TMB6tMXGaFBCAUw1RjwPNg/0?wx_fmt=png)
![](http://mmbiz.qpic.cn/mmbiz_png/9OwLibM3EYapDneicA3iaxGJ0gLb7JvMfO6YqfxYwvvcWiaGNiaehVfP9Z1fP6K9x11iafiaRLoX4m2a2vN8ibPEOCyQTg/0?wx_fmt=png)
其实flowJS的用法并不限于上面demo列出的方式,比如你可以试着在某一步中连续调用几次this.next(),你会发现下一步会被触发多次。想要知道更多用法,可以把我们平时看到的流程图信息套用到里面去实现。
可能有人会用Promise来跟flowJS对比,其实Promise更多的是为了解决JS异步回调的问题,而flowJS不仅也能解决异步回调问题,还能让代码看起来更加语义化和流程化,使得代码更具可读性。
特别是在处理那种比如提交一个数据前,需要做一连串的校验和接口调用的时候,会更加适合,如果哪天需要在中间穿插一个校验或接口调用,只需要往流程中添加一步就可以了,完全做到松耦合。