react redux Reduc-saga实现(1) take put takeEvery createSagaMiddleware等

工作原理

  • sages采用Generator函数来yield Effects(包含指令的文本对象)
  • Generator函数的作用可以暂停执行,再次执行的时候从上次暂停的地方继续执行
  • Effect是一个简单的对象,该对象包含一些给Middleware解释执行的信息。
  • 你可以通过使用effects API如 frok, call, put,cancel等来创建Effect。

Reduc-saga分类

  • worker saga做左右的工作比如调用api,进行异步请求。获取异步封装结果。
  • wather sage监听被dispatch的actions。当接受action或者知道其被触发的时候,调用worker执行任务。
  • root saga立即启动saga的入口
    在这里插入图片描述

复习generator

在这里插入图片描述
带*的function就是生成器,生成器执行会返回迭代器,yield后面的值会作为value在这里插入图片描述
并且,next中的值会作为上次yield的结果

使用

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
will_ADD是通知watcher saga,而下面的put才是真正执行store.dispatch方法。
看效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述每次点击都会执行到rootSaga中去,然后take put,因为for循环是三次所以只能触发3次,接着再触发就没有效果。
takeEvery的用法:
在这里插入图片描述
takeEvery不像take,没有监听到对应的action就阻塞,takeEvey不会阻塞代码运行,它更像是监听,在检测到对应的aciton之后,就会执行第二个参数。
如:
在这里插入图片描述
在这里插入图片描述

  • redux-saga用的比较少,这里主要是实现其原理

实现redux-saga

实现take put

take用来监听某个对应的action,put用来派发action。
在这里插入图片描述
take,put返回一个指令对象。take主要用来监听action,put用来派发action

在saga中间件核心,就是执行rootSaga。在这里插入图片描述

实现createSagaMiddleware

架构:
在这里插入图片描述
返回的中间件有run方法,在这里插入图片描述
在这里引入了两个方法,一个runsaga,用来驱动saga执行,一个stdChannel,用来实现发布订阅。

runsaga核心原理

在这里插入图片描述
可以看到runSaga就是用来驱动传入的generator执行,直到遍历结束。
接着看在这里插入图片描述我们的runsaga接受两个参数。原理是一样的,也是驱动generator的执行,当监听到指令对象TAKE的时候,它会调用channel.take方法去订阅这个动作。此时并没有执行next,所以会在这里阻塞,不会像下执行。
channel就像是派发订阅器,用来订阅某个特定的action,当有人派发action的时候,他也会把对应的action派发到订阅者身上。
在这里插入图片描述
如图,channel主要实现两个方法,take,putAction(源码是put)。
take用来将第二个参数,就是generator执行器的next,存放到数组里面去。(收集订阅者),putAction可以看看主要在哪执行
在这里插入图片描述
在用户派发action的时候执行,执行putAction就会遍历订阅者数组,如果该action是跟某个订阅者一样的,就执行该订阅者对应的next函数,继续走到下一个yield。
所以整个流程,会等我们派发action的时候,generator才会继续往下走。在这里插入图片描述

take的nect执行完毕后,走到下一个yield,此时是put操作,所以直接获取action派发就可以了,还必须调用next()往下走到下一个yieled。因为Put操作不会阻塞流程。看效果:
在这里插入图片描述
在这里插入图片描述

最开始初始化的时候,停在了take订阅部分。阻塞了。接着派发action
在这里插入图片描述

继续往下走的时候,就到了putAction,执行两边是因为第二次到put的时候会dispatch一个action,put的时候不会阻塞流程,所以会j继续next,到下一个yield,依然是take订阅will_ADD。在这里插入图片描述
执行三次后,没有订阅了,不管再怎么派发action,都无效。

支持产出iterator

什么意思呢?如
在这里插入图片描述
我们yield的是一个迭代器。但我们现在不支持。在这里插入图片描述
我们这里只有put和take,所以需要做判断。
在这里插入图片描述
如果下次next得到的是一个迭代器,就开启一个子进程继续驱动迭代器运行,他不会干扰主进程的工作。在这里插入图片描述
效果一样。

takeEvery的实现

takeEvery在监听到action的时候就会执行第二个参数,并且不会阻塞。
并且takeEvery没有次数限制,也就是一旦监听,就会一直监听,不像take,只会监听一次,在putAction的时候就会取消监听了。有点像on和once的关系。
实现思路:通过无限调用take实现无限次监听,而且开启子saga的运行,不阻塞主要函数的运行。
在这里插入图片描述
在这里插入图片描述
这样第一个识别到fork的时候,就会开启子saga,执行
在这里插入图片描述
然后无限次通过take监听actionType,当监听到的时候,就往下,执行第二个参数,也是个generator。
效果:
在这里插入图片描述
在这里插入图片描述
订阅成功,但是第一个generator已经执行完毕了。在这里插入图片描述
没有限制,但一次执行完之后又会继续监听will_ADD。无限循环。
这样takeEvery就实现完毕了。

  • 总结:
    • redux-saga采用generator函数,通过rootSaga开启入口,通过watcher saga来监听aciton,通过worker saga来工作。
    • 再具体就是,通过rootSaga(generator函数)来进行中断,执行。通过take,put等方法返回对应的指令对象。然后通过执行rootSaga来获取指令对象,如take对象就通过channel进行监听,并且阻塞rootSaga的运行,直到用户dispatch 对应的action,就通过channel.putAction去识别判断通知订阅者,订阅者通过执行take时候的Next继续往下走,走到下一层yield put,遇到Put指令对象直接dispatch即可。
    • takeEvery可以循环监听,并且不会阻塞。他的实现思路就是通过死循环无限监听take。然后执行第二个参数。而他会作为子进程去运行,不会阻塞主进程。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coderlin_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值