【发布时间】:2021-06-02 15:54:04
【问题描述】:
我正在学习 Redux 基础教程。在'Writing Custom Middleware' 部分,我们了解到中间件是由一系列三个嵌套函数编写的,如下所示:
// Outer function:
function exampleMiddleware(storeAPI) {
return function wrapDispatch(next) {
return function handleAction(action) {
// Do anything here: pass the action onwards with next(action),
// or restart the pipeline with storeAPI.dispatch(action)
// Can also use storeAPI.getState() here
return next(action)
}
}
}
exampleMiddleware解释如下:
exampleMiddleware:外层函数其实就是“中间件” 本身。它会被applyMiddleware调用,接收一个storeAPI 包含商店的 {dispatch, getState} 函数的对象。这些 是相同的 dispatch 和 getState 函数,它们实际上是 商店。 如果你调用这个 dispatch 函数,它会发送 action 到中间件管道的开头。这只会被调用一次。
我不明白倒数第二句 (If you call this dispatch function, it will send the action to the start of the middleware pipeline) 是什么意思,所以我尝试在示例应用程序的 src/exampleAddons/middleware.js 提供的中间件之一中调用 store.dispatch(action) 以查看发生了什么并得到“太多递归”。 Here's the demo.
所以storeAPI.dispatch() 是所有中间件组合的组合 调度函数,而不是原始商店的dispatch,这可以解释递归。 但是storeAPI.dispatch() 有什么用呢?我是不是用错了?
在applyMiddleware的source:
function applyMiddleware(...middlewares) {
return createStore => (...args) => {
// ...1) createStore is called and the resulting store is saved as `store`
const store = createStore(...args)
// ...2) a `dispatch` variable is defined and assigned some function
let dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
// ...3) a middlewareAPI object is defined containing the store's getState method and the `dispatch` function from 2).
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
// ...4) the middlewares passed to applyMiddleware are called with the `middlewareAPI` object from 3) and the resulting functions are saved in array `chain`.
const chain = middlewares.map(middleware => middleware(middlewareAPI))
// ...5) the middlewares are composed and the resulting "composed" middleware function is called with `store.dispatch`.
// This returns a composed dispatch function that chains together the `handleAction` functions of all the middlewares passed to applyMiddleware.
// This composed dispatch gets assigned to the `dispatch` variable from 2).
// Since the `storeAPI.dispatch` is referencing this variable, calling `storeAPI.dispatch` now calls the composed middleware function, which causes the infinite loop.
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
无限循环似乎是上述注释中第 5 步重新分配的结果。但我不确定我的推理是否正确,或者我是否正确使用了storeAPI.dispatch。感谢社区在这里提供的任何指导,因为我找不到任何调用 storeAPI.dispatch() 的中间件示例。
【问题讨论】:
-
This discussion 阐明了一些用法。
storeAPI.dispatch似乎对于有条件地在中间件中分派一个动作很有用,例如if (condition) { storeAPI.dispatch(someOtherAction) } else { next(action) }- 如果条件为真,则 someOtherAction 将通过中间件管道传递,否则当前操作将传递到下一个中间件。你可以看到这个模式在使用here。 -
在文档中有一个这样的例子会有所帮助。我知道
storeAPI.dispatch'重新启动' 中间件链,但我不知道为什么这是一个有用的功能,直到我看到我之前评论中的链接。 -
storeAPI.dispatch(action) 将再次调度该操作,因此 redux 将运行将再次调用
storeAPI.dispatch(action)的中间件,因此 redux 将运行将再次调用storeAPI.dispatch(action)的中间件,这是你的无限循环。这就像编写一个永不停止循环的递归函数:const recur = (arg)=>recur(arg) -
如果您查看 thunk 实现,您会发现如果操作是函数,它将不会调用 next:
const thunkMiddleware = ({getState,dispatch}) => next => action => typeof action === 'function' ? action(dispatch,getState) : next(action)
标签: javascript reactjs redux react-redux