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

Posted lin-fighting

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react redux Reduc-saga实现 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。然后执行第二个参数。而他会作为子进程去运行,不会阻塞主进程。

以上是关于react redux Reduc-saga实现 take put takeEvery createSagaMiddleware等的主要内容,如果未能解决你的问题,请参考以下文章

React-Redux 知识点 及 实现数据共享案例

react-redux

React-Redux-实现原理

Redux和React-Redux的实现:中间件的原理和applyMiddlewareThunk的实现

react-redux原理

react + redux 实现幻灯片