多个 redux-sagas

Posted

技术标签:

【中文标题】多个 redux-sagas【英文标题】:Multiple redux-sagas 【发布时间】:2017-02-01 15:51:27 【问题描述】:

我使用 react-redux 和 redux-saga 进行来自 this 示例的 API 调用。我的目标是使用不同的 url 进行另一个 API 调用,并在不同的页面中使用它们。如何实现?

传奇:

import  take, put,call  from 'redux-saga/effects';
import  takeEvery, delay ,takeLatest from 'redux-saga';
function fetchData() 
    return  fetch("https://api.github.com/repos/vmg/redcarpet/issues?state=closed")
    .then(res => res.json() )
    .then(data => ( data ) )
    .catch(ex => 
        console.log('parsing failed', ex);
        return ( ex );
    );

function* yourSaga(action) 
    const  data, ex  = yield call(fetchData);
    if (data)
    yield put( type: 'REQUEST_DONE', data );
    else
    yield put( type: 'REQUEST_FAILED', ex );

export default function* watchAsync() 
    yield* takeLatest('BLAH', yourSaga);

export default function* rootSaga() 
    yield [
        watchAsync()
    ]

应用:

import React,  Component  from 'react';
import  connect  from 'react-redux';
class App extends Component 
    componentWillMount() 
        this.props.dispatch(type: 'BLAH');
    
    render()
       return (<div>
            this.props.exception && <span>exception: this.props.exception</span>
            Data: this.props.data.map(e=><div key=e.id>e.url</div>)

          </div>);
    

export default connect( state =>(
    data:state.data , exception:state.exception
))(App);

我的目标是制作另一个传奇,我将在另一个组件中使用它,并且两者都不会互相干扰。这可能吗?

【问题讨论】:

根据您对 Github here 的评论,我已修改您的示例以显示使用两个不同的 API 调用。您应该能够对其进行扩展以使其工作:webpackbin.com/VkdjuU02Z 【参考方案1】:

自从发布最后一个答案以来,这已经发生了一些变化。如https://redux-saga.js.org/docs/advanced/RootSaga.html 所述,创建root saga 的首选方法是使用spawn

export default function* rootSaga() 
  yield spawn(saga1)
  yield spawn(saga2)
  yield spawn(saga3)

spawn 是一种效果,它将断开您的子 saga 与其父级的连接,使其失败而不会使其父级崩溃。这仅仅意味着即使一个 saga 失败,rootSaga 和其他 saga 也不会被杀死。 还有一种方法可以恢复失败的 sagas(更多信息可在上面提到的链接中找到)。

【讨论】:

对我来说很好【参考方案2】:

Redux Saga 在最新版本 (0.15.3) 中使用 all 函数将多个 saga 组合成一个根 saga 用于 Redux 存储。

import  takeEvery, all  from 'redux-saga/effects';

...

function *watchAll() 
  yield all([
    takeEvery("FRIEND_FETCH_REQUESTED", fetchFriends),
    takeEvery("CREATE_USER_REQUESTED", createUser)
  ]);


export default watchAll;

在 Redux 存储中,您可以将根 saga 用于 saga 中间件:

import  createStore, applyMiddleware  from 'redux';
import createSagaMiddleware from 'redux-saga';

import rootReducer from './reducers';
import rootSaga from './sagas';

const sagaMiddleware = createSagaMiddleware();
const store = createStore(
  rootReducer,
  applyMiddleware(sagaMiddleware)
);

sagaMiddleware.run(rootSaga)

【讨论】:

这很有帮助:) 阅读 api 文档时,它说all 方法类似于Promise#all。这里引用 “创建一个 Effect 描述,指示中间件并行运行多个 Effects 并等待它们全部完成”。这是不同的方法吗?如果我只有一堆不同的传奇,我应该运行all 方法吗?导出yield takeLatest()all([ yield takeLatest() ]) 列表【参考方案3】:

当然,这就是 sagas 的全部意义所在。

一个典型的应用程序会有多个 sagas 在后台等待,等待一个特定的动作/动作(take 效果)。

以下是如何从redux-saga issue#276 设置多个 saga 的示例:

./saga.js

function* rootSaga () 
    yield [
        fork(saga1), // saga1 can also yield [ fork(actionOne), fork(actionTwo) ]
        fork(saga2),
    ];

./main.js

import  createStore, applyMiddleware  from 'redux'
import createSagaMiddleware from 'redux-saga'

import rootReducer from './reducers'
import rootSaga from './sagas'


const sagaMiddleware = createSagaMiddleware()
const store = createStore(
  rootReducer,
  applyMiddleware(sagaMiddleware)
)
sagaMiddleware.run(rootSaga)

【讨论】:

我应该在此处添加任何内容吗?导出默认连接( state =>( data:state.data , exception:state.exception ))(App); 以及如何在组件本身中定义它必须获得哪些 saga 属性? 不,组件与 sagas 完全分离。你在组件中调度动作,sagas 拦截某些动作(使用take)。有点类似于reducers。 在这里使用 spawn 会更好吗?有什么理由让它们与根传奇联系起来吗? @bigmadwolf,如果您希望 rootSaga 在单个子崩溃时终止。这取决于您的用例 - more about that here。此外,明确产生 all 更好,因为 yielding array will be deprecated。

以上是关于多个 redux-sagas的主要内容,如果未能解决你的问题,请参考以下文章

LaTeX输入单个点横向多个点竖向多个点斜向多个点

多个网格、多个 VBO、多个 VAO、OpenGL 4.1

mysql添加多个字段&删除多个字段

部分之间的多个自定义 TableviewCell 上的多个自定义 UICollectionView

Symfony 2 与多个提供商、多个防火墙和多个主机的安全问题

表示多个组的多个列[重复]