redux-saga takeLeading 动作加上附加参数

the*_*ebe 6 ecmascript-6 redux redux-saga react-redux

我已经实现了一个 redux 效果takeLeading,如果 saga 当前正在运行,它将忽略后续操作:

export const takeLeading = (patternOrChannel, saga, ...args) => fork(function*() {
  while (true) {
    const action = yield take(patternOrChannel);
    yield call(saga, ...args.concat(action));
  }
});
Run Code Online (Sandbox Code Playgroud)

我在我的应用程序中使用它来获取 API,其中我的 API 中的每个端点都有自己的操作类型。所以对于GET方法来说,如果请求已经在应用程序的其他地方被分派,那么阻塞是很有用的。传奇看起来像:

return function* () {
    yield all([takeLeading(GET_USER_ID, callApiGen), takeLeading(GET_WIDGET_ID, callApiGen)]);
}
Run Code Online (Sandbox Code Playgroud)

明显的问题是,如果我想获得两个不同的用户 ID,第二个将被阻止,因为它也有操作类型 GET_USER_ID。除了为每个可能的参数制定不同的操作之外,有没有一种方法可以实现一些takeLeadingForFunc(<action>, (action) => <id>, saga)让我保持为每个请求类型指定一个效果的简洁格式,但允许我在不同时不阻塞<id>?我试图总结takeLeading与takeEvery实现的东西,但不能完全得到它。

编辑:

我有这样的工作:

export const takeLeadingForFunc = (f) => (patternOrChannel, saga, ...args) => fork(function*() {
  let takeLeadings = {};
  while (true) {
    const action = yield take(patternOrChannel);
    if (!(f(action) in takeLeadings)) {
      yield call(saga, ...args.concat(action))
      takeLeadings[f(action)] = yield takeLeading((ac) => f(ac) === f(action) && ac.type === action.type, saga, ...args)
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

它需要一个f应该返回原语的提取器函数。这感觉有点 hacky,所以想知道是否有更惯用的方法来做到这一点。