} } } 复制代码 这其实就相当于一个Redux中间件的范式了: 一个中间件接收store作为参数,会返回一个函数 返回的这个函数接收老的dispatch函数作为参数(也就是上面的next...put(action):put的参数是action,他唯一的作用就是触发对应事件的回调运行。...channel对应的源码可以看这里:github.com/redux-saga/… 有了channel之后,我们的中间件里面其实只要再干一件事情就行了,就是调用channel.put将接收的action...take是注册一个事件到channel上,当事件过来时触发回调,需要注意的是,这里的回调仅仅是迭代器的next,并不是具体响应事件的函数。...Redux-Saga增强了Redux的dispatch函数,在dispatch的同时会触发channel.put,也就是让Redux-Saga也响应回调。
redux 提供的中间件机制是不是可以用来放这些异步过程呢?...通过 redux-thunk 中间件,我们可以把异步过程通过函数的形式放在 dispatch 的参数里: const login = (userName) => (dispatch) => { dispatch...function (action) { const result = next(action);// 把 action 透传给 store channel.put(action..., action.account) yield put({ type: 'loginSuccess', loginInfo }) } catch (error) { yield...put({ type: 'loginError', error }) } } function* logout() { yield put({ type: 'logoutSuccess'})
call 就像 put, 返回一个 Effect,告诉 middleware 使用给定的参数调用给定的函数。...redux-saga 使用 PUT 来描述dispatch 一个 action 到 Store 而不是直接dispatch action 的原因也是为了方便测试。...: 'PRODUCTS_REQUEST_FAILED', error }) } 常用API Saga 辅助函数 构建在 Effect 创建器之上的辅助函数。...'}) } 2.使用拉取(pull)模式,我们可以在同一个地方写控制流,而不是重复处理相同的 action。...fn: Function – 一个 Generator 函数,或返回 Promise 的普通函数 args: Array – 传递给 fn 的参数数组。 返回一个 Task 对象。
前言 React的作用View层次的前端框架,自然少不了很多中间件(Redux Middleware)做数据处理, 而redux-saga就是其中之一,目前这个中间件在网上的资料还是比较少,估计应用的不是很广泛...put({type: "FETCH_FAILED", error}) } } select 作用和 redux thunk 中的 getState 相同。...(3)redux-thunk的缺点 hunk的缺点也是很明显的,thunk仅仅做了执行这个函数,并不在乎函数主体内是什么,也就是说thunk使 得redux可以接受函数作为action,但是函数的内部可以多种多样...){ console.log(error); }); }; 从这个具有副作用的action中,我们可以看出,函数内部极为复杂。...这个描述对象包含了所需要调用的方法和执行方法时的实际参数,我们认为只要描述对象相同,也就是说只要调用的方法和执行该方法时的实际参数相同,就认为最后执行的结果肯定是满足预期的,这样可以方便的进行单元测试,
翻看createSagaMiddleware源码,可以很清晰的看到,这就是使用了中间件后,我们每次dispatch一个 action 后,在 saga 中间件内会往channel内put这个action...next(action); // 实现了react和saga的交互 channel.put(action); return result; }; }...buffer buffer 是一个固定长度类似队列的数据结构,它有四种类型(下面介绍),对外暴露了几个函数,如下 put 用来缓存 action take 取出一个 action isEmpty 判断...chanel.take(taker)存入一个 taker 函数,chanel.put(action)时,取出 cb 函数执行,action 是用来消费 taker 的 普通 chanel(单播) 特点:...chanel的一些使用参考可以看文档 简化的 eventChanel 实现如下,其实给订阅函数传进一个函数,调用这个函数可以往 Chanel 内 put 东西。
的action分发的时候就执行fetchProducts函数,在这里fetchProducts函数也是Generator函数(tips:注意yield* 就是在Generator内执行另一个Generator...INCREMENT'}) 发起一个action到store - take 第二个参数表示对应匹配的action所要执行的函数。...第一个参数如果是数组的话,表示可以并发监听action - 可以更好的控制状态流 - 如下一个函数控制登陆和登出 //一个简单的登陆逻辑实现 //这个是会被阻塞的 function...isCancelError(error)) yield put({type: 'LOGIN_ERROR', error}) } function* loginFlow() { while...因为是fork所以是不阻塞下面的take['LOGOUT','LOGIN_ERROR']的 const action = yield take(['LOGOUT', 'LOGIN_ERROR']
takeLatest第一个参数是*,即不再匹配某一个具体的action,而是匹配所有的action saga:监听到对应action,启动对应saga。 args:传递给saga函数的参数。...如果takeLatest没有传入args,那么saga函数的参数只有一个,即类型为pattern的action。...如果takeLatest传入了其它args参数,那么saga函数的参数将像这样(args,action)。...({ type: 'increment' }) } put yield put({ type: 'increment' }) put方法的参数为一个action,其作用是产生一个dispatch...行为的Effect,其action就是put中的参数action。
redux-saga负责调度管理 Saga来头不小(1W star不是浪得的),是某篇论文中提出的一种分布式事务机制,用来管理长期运行的业务进程 P.S.关于Saga背景的更多信息,请查看Background...API形式提供,提供各种语义的用来生成Effect的工具函数,例如把dispatch action包装成put、把方法调用包装成call/apply Effect -> 业务操作 在执行时内部进行转换...接入到Redux 提供读/写Redux state的接口(select/put) 提供监听action的接口(take/takeEvery/takeLatest) Sagas组合、通信 task顺序控制...generator形式的一组操作,而不是指redux-saga自身。...会被注入action参数) pull方式的优势在于: 允许更精细的控制 比如可以手动实现takeN的效果(只关注某几次action,用完就释放掉) 以同步形式描述控制流 takeEvery, takeLatest
如果创建帖子成功,我们使用 redux-saga 提供的 effects helpers 函数:put,put 类似之前在 view 中的 dispatch 操作,,来 dispatch 了三个 action...如果发帖失败,我们则使用 put 发起一个 POST_ERROR 的 action 来更新创建帖子失败的信息到 Redux Store,接着使用了 Taro UI 提供给我们的消息框,来显示一个 error...如果获取帖子列表成功,我们使用 redux-saga 提供的 effects helpers 函数:put,put 类似之前在 view 中的 dispatch 操作,,来 dispatch 了两个 action...如果获取帖子列表失败,我们则使用 put 发起一个 POST_ERROR 的 action 来更新获取帖子列表失败的信息到 Redux Store 一些额外的工作 为了创建 watcherSaga 和...如果获取单个帖子失败,我们则使用 put 发起一个 POST_ERROR 的 action 来更新获取单个帖子失败的信息到 Redux Store 一些额外的工作 为了创建 watcherSaga 和
Redux-saga 简介redux-saga 和 redux-thunk 一样, 是一个 Redux 中获取存储异步数据的中间件redux-saga 可以直接拦截 dispatch 派发的 action...action 这回我们派发的 action 就不用像 thunk 一样派发一个函数了图片图片除了通过 takeEvery 来拦截派发的 action 任务方式之外还可以通过 takeLatest 进行监听...action, 那么直接通过 yield takeEvery / yield takeLatest 即可,但是如果我们想同时拦截多个类型的 action, 那么我们就必须借助另外一个函数, all()...(博主所说的是:如果派发下一次同类型 action 的时候,上一次派发的 action 还没有处理完, 也就是上一次的监听方法还没有处理完)如果我们只需要保存一个数据, 那么直接通过 yield put...即可,但是如果我们想同时保存多个数据 , 那么我们就必须借助另外一个函数, all():saga.js:import {takeLatest, put, all} from 'redux-saga/effects'import
简言之:dva想提供一个基于业界react&redux最佳实践的业务框架,以解决用裸redux全家桶作为前端数据层带来的种种问题 编辑成本高,需要在reducer, saga, action之间来回切换...和redux,靠redux中间件机制把redux-saga拉进来一起玩) 到这里差不多封装好了,那么,下面开一些口子增加一点灵活性: 递出一堆钩子(effect/reducer/action/state...自身有没有做到就不好说了(从choo的实现上没看出来有什么拆除堡垒的有效措施) 在API设计上,dva-core差不多保持最小化了: 一份model仅4个配置项 API屈指可数 hook差不多都是必须的...另一个技巧是包一层函数,在外面做参数检查,比如示例中的: function start(container) { //...参数检查 oldAppStart.call(app); } 这样做的好处是把参数检查拿出去了...把自己交给hook,不是什么了不起的技巧,但用法上很有意思,利用iterator可展开的特性,实现了装饰者的效果(交出去一个saga,拿回来一个增强过的saga,类型没变不影响流程)
这么简单的界面和业务逻辑,还是真实场景吗,还需要写神马单元测试吗? 别急,为了保证文章的阅读体验和长度适中,能讲清楚问题的简洁场景就是好场景不是吗?慢慢往下看。...saga 是一种 es6 的生成器函数 - Generator ,我们利用他来产生各种声明式的 effects ,由 redux-saga 引擎来消化处理,推动业务进行。...这里我们来看看获取表格数据的业务代码: import { all, takeLatest, put, select, call } from 'redux-saga/effects'; import *...组合好参数并调用对应的 api 层。 如果正常返回结果,则发送成功 action 通知 reducer 更新状态。 如果错误返回,则发送错误 action 通知 reducer。...这个测试用例的步骤就是利用生成器函数一步步的产生下一个 effect ,然后断言比较。 从上面的注释 3、4 可以看到, redux-saga 还提供了一些辅助函数来方便的处理分支断点。
如果你组织的方式正确,就可以有效地跳过层次结构中的几个层级。...Reducer 函数必须是“纯”的 —— 不能修改它的参数,也不能有副作用(side effect)。...它在底层实际是用了 React 的 Context 特性。 Context 就像是连接每个组件的秘密通道,使用 connect 就可打开秘密通道的大门。...应该 dispatch(increment()) ✅ 牢记 action 生成器是一个平凡无奇的函数。Dispatch 需要 action 是一个对象,而不是函数。...通常我把它们一起称为 “thunk action”。 Action 生成器返回的函数接收两个参数:dispatch 函数和 getState。
redux-saga是一个Redux中间件,用来帮你管理程序的副作用。或者更直接一点,主要是用来处理异步action。...=> console.log(error)) 再到ES6中引入的Generator函数: function* mySaga(value0) { try { var value1 = yield step1...然后我们看下workerSaga,可以看到并不是直接调用异步函数或者派发action,而是通过call()以及put()这样的函数。这就是redux-saga中最为重要的一个概念:Effect。...但是这样的话不好做模拟(mock)测试:我们在测试过程中,一般不会真的执行异步任务,而是替换成一个假函数。实际上,我们只需要确保yield了一个正确的函数,并且函数有着正确的参数。...提供了一系列API函数来生成Effect对象,比较常用的是下面这几个: call:函数调用 select:获取Store中的数据 put:向Store发送action take:在Store
Redux遵循不变性,这意味着我们不改变应用程序状态,而不是返回 新的应用程序状态。 Redux在单个JavaScript对象中管理整个应用程序状态。...default reducer; 在上面的代码中,我们定义了带有两个参数state和的reducer函数action。...库中调用的高阶组件,然后使用state参数定义一个函数mapStatetoProps。...通过使用状态参数, 我们可以访问在reducer函数内部定义的redux状态。...,将dispatch方法作为函数参数。
它是 CSS 的超集,这意味着所有有效的 CSS 也是有效的 SCSS。 缩进语法 ( .sass ) 更不寻常:它使用缩进而不是大括号来嵌套语句,并使用换行符而不是分号来分隔它们。...JSON 字符串出于可读性目的 第二个参数是一个替换函数,因此我们可以传递 null,因为我们不需要替换任何东西。...该函数应防止浏览器的默认行为发布到后端,然后调用传递到 onSave prop 中的函数, 并传递当前创建的新 Project 。...仅当不是 loading 且没有 error 时才显示 More... 按钮, 并处理 More... 按钮的 click 事件并调用 handleMoreClick 。...) 重构 Form 组件,使其调度 saveProject 操作,而不是将函数作为 prop 接收。
接着,我们使用 redux-saga 提供的 effects helpers 函数:put,put 类似之前在 view 中的 dispatch 操作,,来 dispatch 了三个 action:LOGIN_SUCCESS...如果登录失败,我们则使用 put 发起一个 LOGIN_ERROR 的 action 来更新登录失败的信息到 Redux Store,接着使用了 Taro UI 提供给我们的消息框,来显示一个 error...SET_IS_OPENED:设置登录框开启/关闭的信息 我们还从 redux-saga/effects 包中导入了必要的函数: call:在 saga 函数中调用其他异步/同步函数,获取结果 put:...() 来获取此条记录,这个 doc 用于获取指定的记录引用,返回的是这条数据,而不是一个数组。...适配异步 action 的 reducer 我们在前面处理登录时,在组件内部 dispatch 了 LOGIN action,在处理异步 action 的 saga 函数中,使用 put 发起了一系列更新
0 1 dva的介绍 官方文档: https://dvajs.com/guide/ 背景: 使用redux-saga需要在action , reducers,saga三个文件中切换,而可以使用dva框架来简化这一个过程...直接就会执行,一般用于数据的初始化 reducers: 纯函数,如果有异步,必须借助effect effects:副作用(业务逻辑,包含同步和异步) 这里的键名,就是action中type...的字段 payload: action传参数,都放在这里 call() : 表示调用异步函数 如果yield call的是一个Promise对象,那只有在Promise...返回的是resolve方法的情况下,下面跟着的yield put及后面的代码才会执行,若返回了rejector则后面的代码则全部停止执行 put 表示 dispatch action,其他的还有 select..., take, fork, cancel 等 注:yield put直接调用reducer,是堵塞的,同步, 调用非reducer函数,是非堵塞的,异步
这个函数同样接收state和action然后返回新的state,只是这个新的state要符合combineReducers参数的数据结构。...,他接收StoreCreator函数作为参数,同时返回的也必须是一个StoreCreator函数。...而且注意最后一层返回值return function(action)的结构,他的参数是action,是不是很像dispatch(action),其实他就是一个新的dispatch(action),这个新的...所以到这里一个中间件的结构也清楚了: 一个中间件接收store作为参数,会返回一个函数 返回的这个函数接收老的dispatch函数作为参数,会返回一个新的函数 返回的新函数就是新的dispatch函数,...图片 现在我们也可以知道他的中间件为什么要包裹几层函数了: 第一层:目的是传入store参数第二层:第二层的结构是dispatch => newDispatch,多个中间件的这层函数可以compose起来
这个函数同样接收state和action然后返回新的state,只是这个新的state要符合combineReducers参数的数据结构。...StoreCreator函数作为参数,同时返回的也必须是一个StoreCreator函数。...而且注意最后一层返回值return function(action)的结构,他的参数是action,是不是很像dispatch(action),其实他就是一个新的dispatch(action),这个新的...所以到这里一个中间件的结构也清楚了:一个中间件接收store作为参数,会返回一个函数返回的这个函数接收老的dispatch函数作为参数,会返回一个新的函数返回的新函数就是新的dispatch函数,这个函数里面可以拿到外面两层传进来的...图片现在我们也可以知道他的中间件为什么要包裹几层函数了:第一层:目的是传入store参数第二层:第二层的结构是dispatch => newDispatch,多个中间件的这层函数可以compose起来,
领取专属 10元无门槛券
手把手带您无忧上云