API 参考
中间件 API
createSagaMiddleware(options)
创建一个 Redux 中间件并将 Sagas 连接到 Redux Store
options: Object
- 传递给中间件的选项列表。目前支持的选项有:-
context: Object
- saga 的初始上下文值。 -
sagaMonitor
: SagaMonitor - 如果提供了 Saga Monitor,中间件将向监视器传递监视事件。 -
onError: (error: Error, { sagaStack: string })
- 如果提供,中间件将用 Sagas 的未捕获错误调用它。对于将未捕获的异常发送到错误跟踪服务很有用。 -
effectMiddlewares
: Function [] - 允许你拦截任何效果,自己解决它并传递给下一个中间件。详细示例请参见此部分 -
channel
: 如果提供,中间件将使用此通道而不是默认的stdChannel()
来进行
take
和put
效果。
-
示例
下面我们将创建一个函数 configureStore
,它将通过一个新的方法 runSaga
来增强 Store。然后在我们的主模块中,我们将使用该方法来启动应用程序的 root Saga。
configureStore.js
import createSagaMiddleware from 'redux-saga'
import reducer from './path/to/reducer'
export default function configureStore(initialState) {
// 注意:将中间件作为最后一个参数传递给 createStore 需要 redux@>=3.1.0
const sagaMiddleware = createSagaMiddleware()
return {
...createStore(reducer, initialState, applyMiddleware(/* 其他中间件, */sagaMiddleware)),
runSaga: sagaMiddleware.run
}
}
main.js
import configureStore from './configureStore'
import rootSaga from './sagas'
// ... 其他导入
const store = configureStore()
store.runSaga(rootSaga)
注释
有关 sagaMiddleware.run
方法的更多信息,请参见下面。
middleware.run(saga, ...args)
动态运行 saga
。只能在 applyMiddleware
阶段之后运行 Sagas。
saga: Function
: 一个生成器函数args: Array<any>
: 提供给saga
的参数
该方法返回一个 任务描述符。
注释
saga
必须是一个返回 生成器对象的函数。然后,中间件将遍历生成器并执行所有产生的效果。
saga
也可以使用库提供的各种效果启动其他 sagas。下面描述的迭代过程也适用于所有子 sagas。
在第一次迭代中,中间件调用 next()
方法来获取下一个效果。然后,中间件执行由下面的 Effects API 指定的产生的效果。同时,生成器将被挂起,直到效果执行结束。在接收到执行结果后,中间件在生成器上调用 next(result)
,并将检索到的结果作为参数传递。这个过程重复,直到生成器正常终止或抛出一些错误。
如果执行结果是一个错误(如每个 Effect 创建者所指定的),那么将调用生成器的 throw(error)
方法。如果生成器函 数定义了一个 try/catch
来包围当前的 yield 指令,那么底层的生成器运行时将调用 catch
块。运行时也将调用任何对应的 finally 块。
在取消 Saga 的情况下(无论是手动还是使用提供的效果),中间件将调用生成器的 return()
方法。这将导致生成器直接跳到 finally 块。
效果创建者
注释:
- 下面的每个函数都返回一个普通的 JavaScript 对象,并不执行任何操作。
- 执行是由中间件在上述的迭代过程中进行的。
- 中间件检查每个效果描述并执行适当的操作。
take(pattern)
创建一个 Effect 描述,指示中间件等待 Store 上的指定操作。
生成器将挂起,直到分派一个与 pattern
匹配的操作。
yield take(pattern)
的结果是正在分派的操作对象。
pattern
按照以下规则解释:
-
如果没有参数或
'*'
调用take
,则所有分派的操作都将匹配(例如,take()
将匹配所有操作) -
如果它是一个函数,那么如果
pattern(action)
为真,则操作匹配(例如,take(action => action.entities)
将匹配所有具有(真实的)entities
字段的操作。)
注意:如果在模式函数上定义了
toString
,则将action.type
测试为pattern.toString()
。如果你正在使用像 redux-act 或 redux-actions 这样的操作创建库,这将非常有用。
-
如果它是一个字符串,那么如果
action.type === pattern
,则操作匹配(例如,take(INCREMENT_ASYNC)
) -
如果它是一个数组,那么数组中的每一项都与上述规则匹配,因此支持字符串和函数谓词的混合数组。最常见的用例是字符串数组,因此
action.type
与数组中的所有项匹配(例如,take([INCREMENT, DECREMENT])
,这将匹配类型为INCREMENT
或DECREMENT
的任何操作)。
中间件提供了一个特殊的操作 END
。如果你分派 END 操作,那么所有在 take Effect 上阻塞的 Sagas 将被终止,无论指定的模式如何。如果被终止的 Saga 仍然有一些正在运行的 forked 任务,它将等待所有子任务终止后再终止任务。
takeMaybe(pattern)
与 take(pattern)
相同,但在 END
操作上不会自动终止 Saga。相反,所有在 take Effect 上阻塞的 Sagas 将得到 END
对象。
注释
takeMaybe
的名字来自 FP 类比 - 它就像我们可以有 Maybe(ACTION)
类型的返回类型,所以我们可以处理两种情况:
- 有
Just(ACTION)
(我们有一个操作)的情况 NOTHING
(通道已关闭*)的情况。即我们需要某种方式来映射END
- 内部所有
dispatch
的操作都通过stdChannel
进行,当dispatch(END)
发生时,stdChannel
将被关闭
take(channel)
创建一个 Effect 描述,指示中间件等待从提供的 Channel 接收指定的消息。如果通道已经关闭,那么生成器将立即终止,过程与上述 take(pattern)
描述的相同。
takeMaybe(channel)
与 take(channel)
相同,但在 END
操作上不会自动终止 Saga。相反,所有在 take Effect 上阻塞的 Sagas 将得到 END
对象。查看更多这里
takeEvery(pattern, saga, ...args)
在每个分派到 Store 的与 pattern
匹配的操作上生成一个 saga
。
-
pattern: String | Array | Function
- 更多信息请参阅take(pattern)
的文档 -
saga: Function
- 一个生成器函数 -
args: Array<any>
- 要传递给启动任务的参数。takeEvery
将将传入的操作添加到参数列表中(即,操作将是提供给saga
的最后一个参数)