话不多说,先上源码,中间件意味着要满足redux中间件范式
({state,dispatch})=>(next)=>(action)=>{
balaba......
result=next(action)
balaba.............
return result
}
redux-saga也不例外,
function
sagaMiddleware({
getState,
dispatch }) {
const
sagaEmitter =
emitter()
sagaEmitter.
emit = (
options.
emitter ||
ident)(
sagaEmitter.
emit)
sagaMiddleware.
run =
runSaga.
bind(
null, {
context,
subscribe:
sagaEmitter.
subscribe,
dispatch,
getState,
sagaMonitor,
logger,
onError,
})
return
next
=>
action
=> {
if (
sagaMonitor &&
sagaMonitor.
actionDispatched) {
sagaMonitor.
actionDispatched(
action)
}
const
result =
next(
action)
// hit reducers
sagaEmitter.
emit(
action)
return
result
}
}
后面主要研究 saga 是如何利用中间件属性来完成异步操作的。
各种effect优先级 及处理函数
return (
// Non declarative effect
is.
promise(
effect) ?
resolvePromise(
effect,
currCb)
:
is.
helper(
effect) ?
runForkEffect(
wrapHelper(
effect),
effectId,
currCb)
:
is.
iterator(
effect) ?
resolveIterator(
effect,
effectId,
name,
currCb)
// declarative effects
:
is.
array(
effect) ?
runParallelEffect(
effect,
effectId,
currCb)
: (
data =
asEffect.
take(
effect)) ?
runTakeEffect(
data,
currCb)
: (
data =
asEffect.
put(
effect)) ?
runPutEffect(
data,
currCb)
: (
data =
asEffect.
all(
effect)) ?
runAllEffect(
data,
effectId,
currCb)
: (
data =
asEffect.
race(
effect)) ?
runRaceEffect(
data,
effectId,
currCb)
: (
data =
asEffect.
call(
effect)) ?
runCallEffect(
data,
effectId,
currCb)
: (
data =
asEffect.
cps(
effect)) ?
runCPSEffect(
data,
currCb)
: (
data =
asEffect.
fork(
effect)) ?
runForkEffect(
data,
effectId,
currCb)
: (
data =
asEffect.
join(
effect)) ?
runJoinEffect(
data,
currCb)
: (
data =
asEffect.
cancel(
effect)) ?
runCancelEffect(
data,
currCb)
: (
data =
asEffect.
select(
effect)) ?
runSelectEffect(
data,
currCb)
: (
data =
asEffect.
actionChannel(
effect)) ?
runChannelEffect(
data,
currCb)
: (
data =
asEffect.
flush(
effect)) ?
runFlushEffect(
data,
currCb)
: (
data =
asEffect.
cancelled(
effect)) ?
runCancelledEffect(
data,
currCb)
: (
data =
asEffect.
getContext(
effect)) ?
runGetContextEffect(
data,
currCb)
: (
data =
asEffect.
setContext(
effect)) ?
runSetContextEffect(
data,
currCb)
:
/* anything else returned as is */
currCb(
effect)
)
}