Reactjs 使用ejectSaga取消saga任务时,yield cancelled()不是';t触发

Reactjs 使用ejectSaga取消saga任务时,yield cancelled()不是';t触发,reactjs,redux,react-redux,redux-saga,Reactjs,Redux,React Redux,Redux Saga,我正在使用react样板文件injectSaga/ejectSaga功能(),试图取消我的saga遇到了一个问题 tl;dr-当带有注入saga的组件卸载时,saga取消通过task.cancel()发生,但这不会在实际saga本身中触发(即,yield cancelled()未触发) 我像这样将我的传奇注入容器(使用react router v4和redux): injectSaga函数执行以下神奇功能: export default ({ key, saga, mode }) => W

我正在使用
react样板文件
injectSaga/ejectSaga功能(),试图取消我的saga遇到了一个问题

tl;dr-当带有注入saga的组件卸载时,saga取消通过task.cancel()发生,但这不会在实际saga本身中触发(即,
yield cancelled()
未触发)

我像这样将我的传奇注入容器(使用react router v4和redux):

injectSaga
函数执行以下神奇功能:

export default ({ key, saga, mode }) => WrappedComponent => {
  class InjectSaga extends React.Component {
    static WrappedComponent = WrappedComponent;
    static contextTypes = {
      store: PropTypes.object.isRequired,
    };
    static displayName = `withSaga(${WrappedComponent.displayName ||
      WrappedComponent.name ||
      'Component'})`;

    componentWillMount() {
      const { injectSaga } = this.injectors;

      injectSaga(key, { saga, mode }, this.props);
    }

    componentWillUnmount() {
      const { ejectSaga } = this.injectors;

      ejectSaga(key);
    }

    injectors = getInjectors(this.context.store);

    render() {
      return <WrappedComponent {...this.props} />;
    }
  }

  return hoistNonReactStatics(InjectSaga, WrappedComponent);
};
saga注入工作正常-每次组件安装时,我都能清楚地看到在redux中调用和捕获的操作。在
react样板文件
中的特定
sagaInjectors.js
文件中,我找到了取消注入的sagas的特定行:

if (Reflect.has(store.injectedSagas, key)) {
  const descriptor = store.injectedSagas[key];
  if (descriptor.mode && descriptor.mode !== DAEMON) {
    // the task is cancelled here
    descriptor.task.cancel();
    // we verify that the task is cancelled here - descriptor.task.isCancelled() returns true if we log it

    // Clean up in production; in development we need `descriptor.saga` for hot reloading
    if (process.env.NODE_ENV === 'production') {
      // Need some value to be able to detect `ONCE_TILL_UNMOUNT` sagas in `injectSaga`
      store.injectedSagas[key] = 'done'; // eslint-disable-line no-param-reassign
    }
  }
}

My
yield cancelled()
块从未运行,尽管任务已成功取消。关于取消传奇的工作原理,我有什么遗漏吗?有没有一种简单的方法可以让我轻松地处理我的传奇清理逻辑,以便在传奇即将被取消时使用?

我想你误解了任务取消在redux传奇中的作用

  • watchSizesDraftsAga()
    相对应的任务自行完成
  • 然后
    task.cancel()
    什么也不做

  • yield cancelled()

  • watchSizesDraftsAga()
    相对应的任务自行完成
  • 然后
    task.cancel()
    什么也不做

  • yield cancelled()。谢谢你的帮助!嗯,我觉得自己像个白痴——这就是当你花太多时间看东西时会发生的事情。谢谢你的帮助!
    
    export function* watchSizesDraftsSaga() {
      try {
        let stuffWeLookingFor = yield select(selectStuff());
    
        // waiting for stuff here
    
        yield put( moveStuffOver(stuffWeLookingFor) );
        // everything works fine here, page works as expected and stuff has been found
      } finally {
        if (yield cancelled()) {
          // PROBLEM: when the saga is ejected via ejectSaga, this condition never happens
          yield put( cleanStuffUp() );
        }
      }
    }
    
    if (Reflect.has(store.injectedSagas, key)) {
      const descriptor = store.injectedSagas[key];
      if (descriptor.mode && descriptor.mode !== DAEMON) {
        // the task is cancelled here
        descriptor.task.cancel();
        // we verify that the task is cancelled here - descriptor.task.isCancelled() returns true if we log it
    
        // Clean up in production; in development we need `descriptor.saga` for hot reloading
        if (process.env.NODE_ENV === 'production') {
          // Need some value to be able to detect `ONCE_TILL_UNMOUNT` sagas in `injectSaga`
          store.injectedSagas[key] = 'done'; // eslint-disable-line no-param-reassign
        }
      }
    }