Я надеюсь, что кто-то сможет указать мне правильное направление, потому что я борюсь с сочетанием параллелизма и способностью отменить поставленных в очередь запросов в rx js. Я собираюсь попытаться объяснить это в последовательных событиях. Скажем, у нас есть наблюдаемая А, которая получает массив строк.
События: А наблюдает: ['dog', 'cat', 'elephant', 'tiger'] В нисходящем направлении проверяется, кэшируется ли сетевой ответ строки если он существует в кеше, он получает его из кеша, если нет, то запрашивает его из Интернета и сохраняет наблюдаемое в кеш с помощью publishReplay / shareReplay. Существует ограничение на 2 сетевых запроса одновременно, поэтому он пытается извлечь «собака» и «кошку» из API (эта операция занимает более 2000 мс). Через 1000 мс A наблюдает другой набор значений: ['dog', 'rat', 'horse', 'rabbit'].
Далее должно произойти следующее. Я не хочу, чтобы запросы "собака" и "кошка" были отменены, я хочу, чтобы они закончили свой запрос, но слова "слон" и "тигр" с первого запроса я хочу игнорировать. Как только «собака» и «кошка» получают ответ «крыса» и «лошадь» во втором кадре, должны быть запрошены из сети, и, наконец, когда запрашивается любое из этих разрешений «кролик».
Здесь мой текущий код. Я попытался переключиться между отсрочкой и для для networkObservable, и поведение отличается, и ни то, ни другое я не хочу.
const cache = new Map();
// Fake Promise to fake a api request
function later(delay, value) {
console.log('requesting', value);
return new Promise(resolve => setTimeout(resolve, delay, value));
}
const testObservable = of(['dog', 'rat', 'horse', 'rabbit']).pipe(
delay(1000),
startWith(['dog', 'cat', 'elephant', 'tiger'])
);
testObservable.pipe(
map(array => from(array).pipe(
publish(arrayObservable => {
const cachedObservable = arrayObservable.pipe(
filter(id => cache.has(id)),
flatMap(id => cache.get(id), 1)
);
const uncachedObservable = arrayObservable.pipe(
filter(id => !cache.has(id)),
flatMap(id => {
const networkObservable = from(later(2000, id)).pipe(
tap(e => console.log('response', e)),
map(e => 'parsed: ' + e),
tap(e => console.log('parsed', e)),
publishReplay(1),
refCount(),
take(1)
);
cache.set(id, networkObservable);
return networkObservable;
}, 2)
);
return merge(cachedObservable, uncachedObservable);
})
)),
switchAll()
)
Это приводит к выводу:
requesting dog
requesting cat
requesting rat
requesting horse
response dog
parsed parsed: dog
response rat
parsed parsed: rat
requesting rabbit
response horse
parsed parsed: horse
response rabbit
parsed parsed: rabbit
Какой близко к желаемому поведению, но с одним явным недостатком. Требуется крыса и лошадь, и она не ждет, пока собака и кошка решат, прежде чем будут казнены. Тем не менее, «тигр» и «слон» были правильно расположены, поэтому функциональность работает.
Нужно ли мне создавать отдельную тему, которая обрабатывает запросы?