【问题标题】:redux-saga when to use fork?redux-saga 什么时候使用 fork?
【发布时间】:2017-03-21 21:34:53
【问题描述】:

以下两种方法有什么区别?

export function* watchLoginUser() {
  yield takeEvery(USER_LOGIN, loginUser)
}
export function* watchLogoutUser() {
  yield takeEvery(USER_LOGOUT, logoutUser)
}
export function* watchGetParties() {
  yield takeEvery(PARTIES_GET, getParties)
}
export default function* root() {
  yield [
    fork(watchLoginUser),
    fork(watchLogoutUser),
    fork(watchGetParties)
  ]
}
export default function* root() {
  yield [
    takeEvery(USER_LOGIN, loginUser),
    takeEvery(USER_LOGOUT, logoutUser),
    takeEvery(PARTIES_GET, getParties)
  ]
}

什么时候需要使用fork,什么时候不需要?

【问题讨论】:

    标签: reactjs redux redux-saga


    【解决方案1】:

    一般来说,fork 在 saga 需要启动非阻塞任务时很有用。这里的非阻塞意味着:调用者启动任务并继续执行而不等待它完成。

    这在很多情况下都有用,但主要有两种情况:

    • 按逻辑域对 saga 进行分组
    • 保留对任务的引用以便能够取消/加入它

    您的顶级传奇可以是第一个用例的示例。你可能会有类似的东西:

    yield fork(authSaga);
    yield fork(myDomainSpecificSaga);
    // you could use here something like yield [];
    // but it wouldn't make any difference here
    

    authSaga 可能包含以下内容:

    yield takeEvery(USER_REQUESTED_LOGIN, authenticateUser);
    yield takeEvery(USER_REQUESTED_LOGOUT, logoutUser);
    

    您可以看到此示例与您建议的相同,使用 fork 调用 saga 会产生 takeEvery 调用。但在实践中,您只需要出于代码组织目的执行此操作。 takeEvery 本身就是一个分叉任务,所以在大多数情况下,这将是多余的。

    第二个用例的示例如下:

    yield take(USER_WAS_AUTHENTICATED);
    const task = yield fork(monitorUserProfileUpdates);
    yield take(USER_SIGNED_OUT);
    yield cancel(task);
    

    您可以在此示例中看到 monitorUserProfileUpdates 将在调用者 saga 恢复时执行,并等待 USER_SIGNED_OUT 操作被调度。它还可以保留对它的引用,以便在需要时取消它。

    为了完整起见,还有另一种启动非阻塞调用的方法:spawnforkspawn 的不同之处在于错误和取消如何从子传奇冒泡到父传奇。

    【讨论】:

      【解决方案2】:

      通常fork 在某些有多个 API 调用调度的情况下变得更有用,原因是您可以通过从任务中实例化取消来拒绝这些获取,例如cancel(task1);

      如果最终用户强行退出应用程序或其中一项任务失败而导致您的指令、策略和逻辑出现问题并且取消或终止您的 saga 上的当前处理任务可能是合理的,则很有用;

      2种方式可以取消任务

      来自redux-saga的文档非阻塞效果取消

      import { take, put, call, fork, cancel } from 'redux-saga/effects'
      
      // ...
      
      function* loginFlow() {
        while (true) {
          const {user, password} = yield take('LOGIN_REQUEST')
          // Non-Blocking Effect which is the fork
          const task = yield fork(authorize, user, password)
          const action = yield take(['LOGOUT', 'LOGIN_ERROR'])
          if (action.type === 'LOGOUT'){
            //cancel the task
            yield cancel(task)
            yield call(Api.clearItem, 'token')
          }
        }
      }
      

      
      import {call, put, fork, delay} from 'redux-saga/effects';
      import someAction from 'action/someAction';
      
      function* fetchAll() {
        yield fork(fetcher, 'users');
        yield fork(fetcher, 'posts');
        yield fork(fetcher, 'comments');
        yield delay(1500);
      }
      
      function* fetcher(endpoint) {
        const res = yield call(fetchAPI, endpoint);
        if (!res.status) {
          throw new Error(`Error: ${res.error}`);
        }
        yield put(someAction({payload: res.payload}));
      }
      
      function* worker() {
        try {
          yield call(fetchAll);
        } catch (err) {
          // handle fetchAll errors
        }
      }
      
      function* watcher() {
        yield takeEvery(BLOGS.PUSH, worker);
      }
      

      欢迎您:)

      【讨论】:

        猜你喜欢
        • 2019-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-22
        • 2018-06-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多