今天群里有个小伙伴问了个问题
成都创新互联公司服务项目包括鲤城网站建设、鲤城网站制作、鲤城网页制作以及鲤城网络营销策划等。多年来,我们专注于互联网行业,利用自身积累的技术优势、行业经验、深度合作伙伴关系等,向广大中小型企业、政府机构等提供互联网行业的解决方案,鲤城网站推广取得了明显的社会效益与经济效益。目前,我们服务的客户以成都为中心已经辐射到鲤城省份的部分城市,未来相信会继续扩大服务区域并继续获得客户的支持与信任!
为什么 saga 不能用 async await 来实现呢?
想必开始接触 redux-saga 的同学都有这个疑问,为啥为要用 generator 的写法,用 async await 行不行。
- import { put, call } from 'redux-saga/effects'
- import { loginService } from '../service/request'
- function* login(action) {
- try {
- const loginInfo = yield call(loginService, action.account)
- yield put({ type: 'loginSuccess', loginInfo })
- } catch (error) {
- yield put({ type: 'loginFail', error })
- }
- }
这个问题我刚开始用 saga 的时候也想问,但后来了解了 saga 的原理就想明白了。
下面我们就来探究一下。
我们从组件把 action 发给 store,这个过程是同步的。
但是有一些异步的过程加在哪里呢?中间件。
redux saga 会先把 action 直接透传给 store,这个过程是同步的。
然后再传递一份给 watcher saga,看一下是否是被监听的 action,如果是交给 worker saga 来处理,worker saga 处理的过程中可以 put 新的 action 到 store,这个过程是异步的。
这就是 redux-saga 的原理,原理上还是比较简单的,亮点在于异步过程的组织上,也就是 generator 上。
为什么说用 generator 来组织异步过程是 redux-saga 的亮点呢?
别急,我们先了解下什么是 generator。
生成器(generator)是一个产生迭代器(iterator)的函数,通过 yield 返回一个个值。
而迭代器是一个有 value 和 done 属性的对象,用于顺序遍历某个集合。
我们可以调用 iterator.next 取到 yield 生成的一个个值。
也可以用 Array.from 或者展开运算符来取,这是 iterator 的特点。
除了 next 方法,迭代器还有 return 和 throw 方法,就像函数里的 return 和 throw 语句一样。
比如用 iterator.return 中止后续流程
用 iterator.throw 抛出错误
也就是说 generator 的执行是要由一个执行器来控制的,什么时候取下一个 yield 出的值,什么时候 next,什么时候 return 什么时候 throw 都是由执行器控制。
执行器可以通过 next、return、throw 的参数传递给 generator 执行后的结果:
上面这段代码就是一个小型 saga 了,原理就这么简单。
那为什么 async await 不行呢?
当 generator 返回的值都是 Promise,那么执行 Promise 以后,只有 resolve 和 reject 两种结果,这个执行器就很固定,那自然可以写一个通用的执行器来自动调用 next、throw 和 return。
这个就是 async await 的原理,只不过被做成了语法糖。
async await 本质上不过是一个 generator 的执行器。
如果 redux-saga 用 async await 实现,那么所有的异步逻辑都要命令式的写在 await 后面,这样会导致异步过程很难测试。所以 redux-saga 自己实现了一个执行器。
再来看这段 saga 的代码:
- import { put, call } from 'redux-saga/effects'
- import { loginService } from '../service/request'
- function* login(action) {
- try {
- const loginInfo = yield call(loginService, action.account)
- yield put({ type: 'loginSuccess', loginInfo })
- } catch (error) {
- yield put({ type: 'loginFail', error })
- }
- }
generator 中 yield 出的不是 promise,而是一个个 effect,这个其实就是一个对象,声明式的告诉 saga 执行器要做什么,而不是命令式的自己实现。
这样 generator 的执行器就根据不同的 effect 做不同的实现:
call effect 有对应的实现、put effect 也有对应的实现,也就是说 saga 的 generator 执行器不像 async await 那样什么都不做,而是有自己的 runtime 在的。
这样有什么好处呢?
现在,我们回到最开始那个问题,redux-saga 能用 async await 实现么?
能,但是 async await 是一个 generator 的自动执行器,没有 runtime 逻辑,要命令式的把异步过程写在 saga 里。如果自己实现一个 generator 执行器,那么就可以把异步过程抽离出来,方便组织、方便测试。用 async await 实现 saga 的话,那就失去了灵魂。
redux-saga 的原理是透传 action 到 store,然后再传一份 aciton 到 saga 组织的异步过程,saga 分为 watcher saga 和 worker saga。watcher saga 判断 action 是否要处理,然后交给 wroker saga 处理。
生成器 generator 是返回迭代器 iterator 的函数,iterator 有 next、throw、return 等方法,需要配合一个执行器来执行。
async await 本质上就是一个 generator 的自动执行器。
用 async await 实现 redux saga 的话,那就要开发者命令式的组织异步过程,还难以测试。
所以 redux-saga 自己实现了一个 generator 执行器,自带 runtime。generator 只要返回 effect 对象来声明式的说明要执行什么逻辑,然后由相应的 effect 实现来执行。
这种声明式的思路除了易于组织异步过程外,还有非常好的可测试性。
generator + saga 执行器的设计是 redux-saga 的灵魂,所以不能用 async await 来实现。
文章标题:为什么Redux-Saga不能用AsyncAwait实现
标题来源:http://www.shufengxianlan.com/qtweb/news6/273406.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联