Ждите обещания разрешить с помощью RxJs

88
7

Я пытаюсь реализовать функцию "сохранить тип" для формы, используя RxJS v5 beta.


Данные должны быть размещены на бэкэнд при вводе пользователем текстовых полей. Я создаю Rx.Subject для запуска новых событий (next()) для ввода нового пользователя и отправки его с помощью HTTP-запросов.


Я использовал этот вопрос в качестве отправной точки: RxJS ждет, пока не будет достигнуто обещание


Однако с решением этой почты отправляется одновременный запрос на бэкэнд.


Моя цель заключается в том, чтобы отправлять только один запрос и откладывать запросы после завершения запроса на выполнение. После завершения запроса должно быть выбрано последнее из ожидающих событий (например, в debounceTime)


Функция example в следующем фрагменте использует подход из связанного вопроса SO. Это отправляет запросы для всех входных значений.


Функция функции workaround использует обещание, хранящееся за пределами "потока", для блокировки и ожидания предыдущего запроса. Это работает и отправляет запрос только для последнего входного значения. Но это, похоже, не соответствует концепции RxJs и чувствует себя взломанным.


Есть ли способ достичь этого с помощью RxJS?


function fakeRequest(value) {
console.log('start request:', value)
return new Promise((resolve) => {
setTimeout(() => resolve(value), 1000);
});
}

function example() {
let subject = new Rx.Subject();

subject
.debounceTime(500)
.switchMap(input => fakeRequest(input))
.subscribe(data => console.log(data))

subject.next('example value 1');
subject.next('example value 2');
subject.next('example value 3');
subject.next('example value 4');
}

function workaround() {
let subject = new Rx.Subject();

let p = Promise.resolve();
subject
.debounceTime(500)
.switchMap(input => p.then(() => input))
.do(input => p = fakeRequest(input))
.subscribe(data => console.log(data))

subject.next('workaround value 1');
subject.next('workaround value 2');
subject.next('workaround value 3');
subject.next('workaround value 4');
}

example();
// workaround();


<script src="https://unpkg.com/@reactivex/rxjs@5.0.0-rc.2/dist/global/Rx.js"></script>

спросил(а) 2021-01-27T20:03:03+03:00 4 месяца, 3 недели назад
1
Решение
88

Если вы хотите запускать запросы по порядку и не отбрасывать ни один из них, используйте concat() или concatMap(). Они ожидают, пока предыдущий Observable не завершится, а затем продолжите следующую.


function fakeRequest(value) {
console.log('start request:', value)
return new Promise((resolve) => {
setTimeout(() => resolve(value), 1000);
});
}

let subject = new Subject();
subject.concatMap(value => Observable.fromPromise(fakeRequest(value)))
.subscribe(value => console.log(value));

subject.next('example value 1');
subject.next('example value 2');
subject.next('example value 3');
subject.next('example value 4');


Отправляется на консоль:

start request: example value 1
example value 1
start request: example value 2
example value 2
start request: example value 3
example value 3
start request: example value 4
example value 4

Смотрите демо-версию: https://jsbin.com/xaluvi/4/edit?js,console


Если вы хотите игнорировать значения, тогда debounce, throttle или audit - все это хорошие варианты.

ответил(а) 2021-01-27T20:03:03+03:00 4 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема