Redux Saga:yield 数组与根 saga 中的 fork 之间的区别

Redux Saga: difference between yield array to fork in the root saga

saga 新手,我在我的 root saga 中使用它:

function* rootSaga() {
    yield [
        cycleRoot(), // fetches root
        cycleChain(), // fetch chain
        cycleChatBadge(), // fetches badge
        watchNotifications(), // navigate on ROOT_DONE
        watchNavigation(), // listen to navigation changes
        watchAppState(), // background/foreground
        watchConnection(), // connection chages
    ];
}

有效。但是我见过使用的示例:

function* rootSaga() {
    yield fork (cycleRoot);
    yield fork (cycleChain);
    ...
}

这两者在启动 root saga 时有什么不同吗?

这里其实有两个区别。

1.使用效果 vs 直接调用 sagas。

redux-saga 库可以直接处理生成生成器,但是这种方法使得在编写测试时很难使用模拟。相反,您可以使用 call 效果。除了使用 call 效果以声明方式编写之外,此代码的工作方式与您的第一个代码段完全相同。 (此外,我在这里使用 all 效果,因为生成数组已被弃用)。

function* rootSaga() {
    yield all([
        call(cycleRoot), 
        call(cycleChain),
        ...
    ]);
}

为了获得更深入的见解(包括测试示例),我建议阅读 redux-saga 文档的这一部分:https://redux-saga.js.org/docs/basics/DeclarativeEffects.html

您可以使用 call 效果来调用函数和 sagas。但是,如果您对编写测试不感兴趣并且确定您永远不会,我发现使用 call 效果来区分调用 sagas(使用 call)和常规函数(直接调用)很有用.

2。使用 fork 而不是 call

第二个区别是,在您的第一个代码段中,您阻止了 rootSaga 的执行,直到所有的传奇都完成。要使它们不阻塞,您可以使用 fork 效果。

function* rootSaga() {
    yield all([
        call(cycleRoot), 
        call(cycleChain),
        ...
    ]);
    console.log('This happens only after all sagas are finished (including fetching etc.')
}

function* rootSaga() {
    yield all([
        fork(cycleRoot), 
        fork(cycleChain),
        ...
    ]);
    console.log('This happens immediately after the sagas are executed - it does not wait for async action like fetching')
}

您可以再次阅读文档中的非阻塞调用:https://redux-saga.js.org/docs/advanced/NonBlockingCalls.html

总而言之 我建议在调用其他 sagas 时始终使用效果(如 call/fork)并使用 fork 效果在根传奇中启动其他传奇,除非有充分的理由阻止它。