作者:飞羽


本文简述:通过对一个开发简单的模块,将iMove带入你的编程世界。

从前,有一个需求

/做一个天气组件的功能。
image.png

一、需求收集

产品的需求描述很简单,天气 widget组件:展示当前用户所在地的天气,可以自己选择地址查询天气。

但是实际上会有很多隐藏的需求:

  • 功能一:初始化获取经纬度,通过经纬度查城市ID,通过城市ID查天气。
  • 功能二:通过城市ID 查询天气API。

但是产品经理多数可能没有考虑到 “边界情况”、“异常情况”。

  • 如何手机所在的地址:通过手机定位GPS信息
    • 如果GPS 没有怎么办?
  • 城市ID 获取不到怎么办?

二、分析需求

这个需求本质上是:

  1. 请求一些API,拿到我们想要的数据
  2. 考虑一些异常情况和边界情况
  3. 输出到视图展示。
  4. 任务完成!

三、准备工作

在开始写代码之前,我们要做一些准备工作,如:安装iMove、以及了解一下 iMove 的简单工作原理。

  1. Mac一台,没有Mac,理论上PC也能开发。
  2. 新建工程:这里使用 react-app 来创建我们的工程

    1. npm init react-app my-app
    2. cd my-app

    确保你的项目目录中有 package.json 和 src 目录。

  3. 初始化 iMove 本地构建器:见 iMove 开发套件 ( https://github.com/imgcook/imove )

    1. imove -i
  4. 启动 imove 本地构建器

    1. imove -d
  5. 打开 imove GUI 地址(也可以本地运行):https://65hzt.sse.codesandbox.io

  6. 你将看到如下iMove 界面,目前还是比较简陋,但是已经足够满足本文的需求了。

    1. 在右上角:提示本地连接成功
    2. ![image.png](https://cdn.nlark.com/yuque/0/2021/png/285525/1614605629447-c82086d9-a2e5-4408-ab21-d644f2cbdee7.png#align=left&display=inline&height=323&margin=%5Bobject%20Object%5D&name=image.png&originHeight=646&originWidth=1204&size=309070&status=done&style=none&width=602)
  7. 不做任何操作,保存(Ctrl+S)后:将在你的开发目录中生成对应 logic 目录。

此时,还没有任何逻辑,我们的开发目录中已经生成了iMove 的 logic出码文件夹,让人非常的安心。
image.png

四、运行 hello iMove

此时我们拖入一个开始节点(后面有说明节点的类型)
image.png
并且点击“编辑”,可以打开代码编辑界面。输入“hello iMove”
image.png
然后点保存。这个时候代码会同步到你的开发目录如下:
(不要介意那个像hash一样的文件名,你会习惯的 >///< )
image.png
如果需要运行 这部分逻辑,只需要 在你的 react 组件中引用 logic.js ,两行代码就能实现。

  1. import Logic from './logic';
  2. Logic.invoke('start'); // 'start' 为逻辑触发名称

五、添加 iMove 节点

然后我们回到 iMove 界面,增加如下几个节点,并且将其链接起来如下:
image.png
分别在 “判断节点”、“处理节点” 添加如下代码

  1. // 开始
  2. export default async function(ctx) {
  3. const message = 'hello iMove ~';
  4. console.log(message);
  5. return { message }
  6. }
  1. // 是否成功
  2. export default async function(ctx) {
  3. return true;
  4. }
  1. // 请求成功
  2. export default async function(ctx) {
  3. console.log('成功', ctx.getPipe());
  4. }
  1. // 请求失败
  2. export default async function(ctx) {
  3. console.log('失败', ctx.getPipe());
  4. }

然后继续回到 react app 你发现页面运行的时候,输出产生了变化~
image.png

可以看到 变量 message 通过 “判断节点” 被传递到了 请求成功 节点。你可以想象水流一样。
image.png

这个时候我们把“判断节点” 改个方向 如下:

  1. // 判断是否成功
  2. export default async function(ctx) {
  3. return false;
  4. }

然后看控制台,神奇的事情发生了:
image.png
“判断节点” 就像开关一样将 水流(pipe) 导向你想要的地方
image.png
是不是非常好理解,这个就是 iMove 的基础特性! Amazing ! ~~

六、监听数据

可以控制流程之后,那么如何监听触发流程的结果以及状态呢?
继续上面的流程。
我们在 “请求成功”、“请求失败”节点 分别添加一行代码,如下:

  1. // 请求 成功
  2. export default async function(ctx) {
  3. console.log('成功', ctx.getPipe());
  4. ctx.emit('action', { status: 'SUCCESS' });
  5. }
  1. export default async function(ctx) {
  2. console.log('失败', ctx.getPipe());
  3. ctx.emit('action', { status: 'FAIL' });
  4. }

然后在你的 react 组件中添加 监听脚本:

  1. import Logic from './logic';
  2. // 监听 action 事件
  3. Logic.on('action', payload => {
  4. console.log(payload);
  5. });
  6. // 'start' 为逻辑触发名称
  7. Logic.invoke('start');

这个时候 控制台就能 捕获到 你触发的 action 事件以及数据。
image.png
看到这里大概就能了解iMove的核心工作方式:

  • 开始节点:**黑色**的圆形,代表事件流的开端。
  • 流程节点蓝色的长方形,事件流的 信息输入节点 (可以给pipe流里注入数据)
  • 判断节点黄色的菱形,事件流的 导流器 (类似:铁路的转向装置,将pipe数据引导至正确的方向)
  • 广播节点绿色的长方形,事件流的 广播节点,负责将 数据流 广播给视图层

有了以上简单理解后,就可以清晰了解 每个节点该做什么,不该做什么。

六、绘制逻辑

image.png
可以通过复制以下数据导入(高级功能,见DSL导入):

以下是流程的DSL:

  1. https://github.com/qilei0529/imove-example/blob/master/.cache/imove_empty.dsl.json

七、编写补全逻辑

以下是补全代码后的DSL:

  1. https://github.com/qilei0529/imove-example/blob/master/.cache/imove.dsl.json

八、连接视图

通过iMove 绘制的图 我们可以清楚的知道在哪里获取数据,从哪里提取异常。
比如:如果要获取,天气数据只需要监听 iMove 中的“请求天气成功”事件就可以。

  1. // 监听 action 事件
  2. Logic.on('action', payload => {
  3. const {
  4. type,
  5. weather
  6. } = payload;
  7. if (type === 'SUCCESS') {
  8. setState({
  9. status: '2', // 模块状态:0 初始 1 加载中 2 正常 4 异常
  10. weather, // 天气数据
  11. })
  12. }
  13. });

九、注意事项

  1. Logic.on 的方法是继承自 EventEmitter ,需要注意它的副作用(重复声明会引起bug)

十、思考 & 展望

可能刚开始上手iMove 的时候,会觉得代码量反而变多了。
但细品,会发现可以做很多有意思的事情,比如:如何将代码节点化? 如何设计好与视图交互的数据结构?

开发方式产生了一些变化?

  1. 先画流程,再写代码成为新的流程。(很多时候流程画完,代码就已经清晰了)
  2. 从视觉上将 业务逻辑 节点化。
  3. 代码的思考过程完全呈现给上下游(后端、测试),再也不怕测试质疑我的代码有问题了。