С помощью redux-saga, как я могу взять Leading, основываясь на параметрах действия, а также на типе? - PullRequest
0 голосов
/ 12 июня 2019

Допустим, я отправляю 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 были завершены, поэтому в этом примере игнорируются только последние 2. Как мне это сделать?

Ура!

1 Ответ

0 голосов
/ 15 июня 2019

Если у вас есть явный список заголовков, вы можете сделать более конкретных наблюдателей, передав функцию вместо типа действия создателю эффекта 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);

Обратите внимание, что я только что записал этот служебный метод, чтобы, возможно, что-то пропустил в реализации.

...