前端时间一直在补大学的知识,很惭愧==,今天带来一个项目中用的知识,目前的技术栈是ant design + dva + koa,至于dva是什么,下面是dva团队的介绍:dva 是基于现有应用架构 (redux + react-router + redux-saga 等)的一层轻量封装。dva 是 framework,不是 library,类似 emberjs,会很明确地告诉你每个部件应该怎么写,这对于团队而言,会更可控。另外,除了 react 和 react-dom 是 peerDependencies 以外,dva 封装了所有其他依赖。dva 实现上尽量不创建新语法,而是用依赖库本身的语法,比如 router 的定义还是用 react-router 的 JSX 语法的方式(dynamic config 是性能的考虑层面,之后会支持)。他最核心的是提供了app.model方法,用于把 reducer, initialState, action, saga 封装到一起。
以后会专门找个时间详细剖析下这个个人非常喜欢的轻量级框架,蚂蚁金服把这套框架结合antd可能以及经把中后台开发方案提升到了一个更为高层级的水平,这个我们以后再说,今天主要是介绍我们的rudex中间件:saga
Redux-Saga
redux-saga 是一个用于管理 Redux 应用异步操作(Side Effects。译注:直译成 “副作用” 不太通顺,所以这里译为 “异步操作” 更好理解)的中间件(又称异步 action)。 redux-saga 通过创建Sagas将所有的异步操作逻辑收集在一个地方集中处理,可以用来代替redux-thunk中间件。
这意味着应用的逻辑会存在两个地方:
Reducers 负责处理 action 的 state 更新。
Sagas 负责协调那些复杂或异步的操作。
Sagas 是通过 Generator 函数来创建的。如果你还不熟悉 Generator,可以在这里找到一些有用的链接。
Sagas 不同于 Thunks,Thunks 是在 action 被创建时调用,而 Sagas 只会在应用启动时调用(但初始启动的 Sagas 可能会动态调用其他 Sagas)。 Sagas 可以被看作是在后台运行的进程。Sagas 监听发起的 action,然后决定基于这个 action 来做什么:是发起一个异步调用(比如一个 Ajax 请求),还是发起其他的 action 到 Store,甚至是调用其他的 Sagas。
在redux-saga的世界里,所有的任务都通用 yieldEffects来完成(译注:Effect 可以看作是 redux-saga 的任务单元)。Effects 都是简单的 Javascript 对象,包含了要被 Saga middleware 执行的信息(打个比方,你可以看到 Redux action 其实是一个个包含执行信息的对象)。redux-saga为各项任务提供了各种 Effect 创建器,比如调用一个异步函数,发起一个 action 到 Store,启动一个后台任务或者等待一个满足某些条件的未来的 action。
因为使用了 Generator,redux-saga让你可以用同步的方式写异步代码。就像你可以使用async/await函数所能做的一样。但 Generator 可以让你做一些async函数做不到的事情。
事实上 Sagas yield 普通对象的方式让你能容易地测试 Generator 里所有的业务逻辑,可以通过简单地迭代 yield 过的对象进行简单的单元测试。
此外,redux-saga启动的任务可以在任何时候通过手动取消,也可以把任务和其他的 Effects 放到 race 方法里以自动取消。
通俗点说,Redux-saga 是一个旨在于在React/Redux应用中更好、更易地解决异步操作(action)的库。主要模块是 saga 会像一个分散的支线在你的应用中单独负责解决异步的action(类似于后台运行的进程)。详细移步:Redux-saga
redux-saga相当于在Redux原有数据流中多了一层,对Action进行监听,捕获到监听的Action后可以派生一个新的任务对state进行维护(当然也不是必须要改变State,可以根据项目的需求设计),通过更改的state驱动View的变更。图如下所示:
用过redux-thunk的人会发现,redux-saga 其实和redux-thunk做的事情类似,都是可以处理异步操作和协调复杂的dispatch。不同点在于:
Sagas 是通过 Generator 函数来创建的,意味着可以用同步的方式写异步的代码
Thunks 是在 action 被创建时才调用,Sagas 在应用启动时就开始调用,监听action 并做相应处理; (通过创建 Sagas 将所有的异步操作逻辑收集在一个地方集中处理)
启动的任务可以在任何时候通过手动取消,也可以把任务和其他的 Effects 放到 race 方法里可以自动取消
入门demo
$ git clone https://github.com/HelianXJ/redux-saga-beginner-tutorial.git
$ git checkout redux-tool-saga// 切到有redux tool的分支配合chorme 的 Redux DevTools 工具查看逻辑更清晰
$ npm i//下载依赖
$ npm run hello//先看项目文件中的hello sagas
启动server成功后view-on:http://172.22.32.14:9966/
由于redux-saga是用ES6的Generators实现异步,incrementAsync 是一个 Generator 函数,所以当我们在 middleware 之外运行它,会返回一个易预见的遍历器对象, 这一点应用在单元测试中更容易写unit。
实际上 redux-saga 所有的任务都通用 yield Effects 来完成。它为各项任务提供了各种 Effect 创建器,可以是:
调用一个异步函数
发起一个 action 到 Store
启动一个后台任务或者等待一个满足某些条件的未来的 action
Redux-Saga优点
流程拆分更细,异步的action 以及特殊要求的action(更复杂的action)都在sagas中做统一处理,流程逻辑更清晰,模块更干净;
以用同步的方式写异步代码,可以做一些async 函数做不到的事情 (无阻塞并发、取消请求)
能容易地测试 Generator 里所有的业务逻辑
可以通过监听Action 来进行前端的打点日志记录,减少侵入式打点对代码的侵入程度
带来的问题和可接受性
action 任务拆分更细,原有流程上相当于多了一个环节。对开发者的设计和抽象拆分能力更有要求,代码复杂性也有所增加。
异步请求相关的问题较难调试排查
资历尚浅,有不当之处还请指正