使用redux-saga,我如何基于动作参数和类型来采用Leading?

时间:2019-06-12 12:20:34

标签: reactjs redux redux-saga

所以说我分派了4个操作来通过redux-saga进行异步调用,如下所示:

{type: REQUEST_API_THING, title: 'Foo'}
{type: REQUEST_API_THING, title: 'Bar'}
{type: REQUEST_API_THING, title: 'Foo'}
{type: REQUEST_API_THING, title: 'Foo'}

...。在分派最后一个动作之前,没有一个动作会完成。如果我将我的传奇故事附上:

yield takeLeading(REQUEST_API_THING, fetchApiThing);

仅第一个请求将被完成。其他将被忽略。我希望所有具有唯一title参数的请求都可以完成,因此在此示例中,仅应忽略最后两个。我该怎么办?

干杯!

1 个答案:

答案 0 :(得分:0)

如果您有明确的标题列表,则可以通过将功能而不是动作类型作为第一个参数传递给take *效果创建者,从而做出更具体的观察者。

yield takeLeading(({type, title}) => type === 'REQUEST_API_THING' && title === 'Foo', fetchApiThing);
yield takeLeading(({type, title}) => type === 'REQUEST_API_THING' && title === 'Bar', fetchApiThing);

如果您事先不知道标题,则此方法将无效。据我所知,Redux-saga没有内置的处理方式,但是您可以这样编写自己的实用程序方法:

function takeLeadingWithParam(typeOrPattern, param, saga, ...args) {
    const instanceMap = new Map();
    return fork(function * () {
        yield takeEvery(typeOrPattern, function* (action) {
            const key = typeof param === 'function' ? param(action) : action[param];
            if (!instanceMap.get(key)) {
                const task = yield fork(saga, action, ...args);
                instanceMap.set(key, task);
                yield join(task);
                instanceMap.delete(key);
            }
        });
    });
}

然后您可以像这样使用它:

yield takeLeadingWithParam('REQUEST_API_THING', 'title', fetchApiThing);

或者像这样一些更复杂的逻辑:

yield takeLeadingWithParam('REQUEST_API_THING', ({id, title}) => id + ':' + title, fetchApiThing);

请注意,我只是写下了该实用程序方法,所以我可能错过了实现中的某些内容。