2016-11-14 3 views
3

Я пытаюсь реализовать функцию «сохранить тип» для формы, используя RxJS v5 beta.Ждите обещания разрешить с помощью RxJs

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

Я использовал этот вопрос в качестве отправной точки: RxJS wait until promise resolved

Однако, с раствором с этого поста, одновременный запрос на внутреннем интерфейсе посылаются.

Моя цель состоит в том, чтобы отправлять только один запрос и отложить запросы до завершения запроса на выполнение. После завершения запроса должно быть выбрано последнее из ожидающих событий (как в случае 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/[email protected]/dist/global/Rx.js"></script>

ответ

3

Если вы хотите запускать запросы в порядке и не отбрасывать ни один из них затем использовать 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 все хорошие выборы.

+0

Спасибо, это помогло. Но проблема, с которой я сталкиваюсь сейчас, заключается в том, что все события, которые были заблокированы обещанием, испускаются, как только обещание будет разрешено. Я бы просто хотел, чтобы последний из них испускал (как это имеет место с 'debounceTime', см. Мое редактирование) – Stefan

+0

@Stefan Итак, что вам нужно? Выпустить все из них или только последний? Похоже, вам нужен оператор 'auditTime()' http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html#instance-method-audit – martin

+0

Извлечь только последний. Я возился с «аудитом», но не мог заставить его работать. Обратная связь очень ценится. – Stefan

Смежные вопросы