Jak mogę utworzyć obserwowalne z opóźnieniem


92

Pytanie

Do celów testowych tworzę Observableobiekty, które zastępują obserwowalne, które byłyby zwracane przez rzeczywiste wywołanie http z Http.

Moje obserwowalne jest tworzone za pomocą następującego kodu:

fakeObservable = Observable.create(obs => {
  obs.next([1, 2, 3]);
  obs.complete();
});

Rzecz w tym, że to obserwowalne emituje natychmiast. Czy istnieje sposób na dodanie niestandardowego opóźnienia do jego emisji?


Tor

Próbowałem tego:

fakeObservable = Observable.create(obs => {
  setTimeout(() => {
    obs.next([1, 2, 3]);
    obs.complete();
  }, 100);
});

Ale to nie działa.



Próbowałem połączyć .create(...)z łańcuchem, .delay(1000)ale to nie zadziałało: Observable_1.Observable.create (...). Delay nie jest funkcją.
Adrien Brunelat

1
Co dokładnie próbujesz osiągnąć?
Günter Zöchbauer

czy subskrybujesz to, co obserwowalne?
shusson

Sfałszuj opóźnienie odpowiedzi HTTP moim własnym obserwowalnym. @shusson tak, klasa, którą testuję, wywołuje usługę (próbuję kpić) dla obserwowalnego, aby ją zasubskrybować.
Adrien Brunelat

Odpowiedzi:


144

Korzystając z następujących importów:

import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/delay';

Spróbuj tego:

let fakeResponse = [1,2,3];
let delayedObservable = Observable.of(fakeResponse).delay(5000);
delayedObservable.subscribe(data => console.log(data));

AKTUALIZACJA: RXJS 6

Powyższe rozwiązanie tak naprawdę już nie działa w nowszych wersjach RXJS (i np. Angular).

Tak więc scenariusz jest taki, że mam tablicę elementów do sprawdzenia za pomocą interfejsu API. API akceptuje tylko jeden element i nie chcę go zabijać, wysyłając wszystkie żądania naraz. Więc potrzebuję czasowego wydania elementów w strumieniu Observable z niewielkim opóźnieniem między nimi.

Użyj następujących importów:

import { from, of } from 'rxjs';
import { delay } from 'rxjs/internal/operators';
import { concatMap } from 'rxjs/internal/operators';

Następnie użyj następującego kodu:

const myArray = [1,2,3,4];

from(myArray).pipe(
        concatMap( item => of(item).pipe ( delay( 1000 ) ))
    ).subscribe ( timedItem => {
        console.log(timedItem)
    });

Zasadniczo tworzy nowe „opóźnione” obserwowalne dla każdego elementu w tablicy. Prawdopodobnie jest na to wiele innych sposobów, ale to zadziałało dobrze i jest zgodne z „nowym” formatem RXJS.


2
Właściwość „of” nie istnieje w typie „typeof Observable”. Czy importujesz Observable z import {Observable} from 'rxjs/Observable';?
Adrien Brunelat

1
Z tej strony: npmjs.com/package/rxjs . Wydedukowałem, że muszę wyraźnie importować z import 'rxjs/add/observable/of';. Czy zdarza ci się robić to samo? Jest to jednak nadal dziwne, ponieważ nie łączy się z .delay (...) i wyświetla błąd, gdy próbuję rxjs/add/observable/delay...
Adrien Brunelat

4
powinny of(item.pipe ( delay( 1000 ) ))być of(item))).pipe(delay(1000)próby rury tablica dał mi błędy
Don Thomas Boyle

1
To właśnie zadziałało w przypadku rxjs6: from ([1, 2, 3, 4, 5, 6, 7]). Pipe (concatMap (num => of (num) .pipe (delay (1000)))). subscribe (x => console.log (x));
robert

1
Rozwiązanie @MikeOne również działało dla mnie. Smutne, że do tak prostej sprawy potrzeba tyle kodu ...
Codev

103

W RxJS 5+ możesz to zrobić w ten sposób

import { Observable } from "rxjs/Observable";
import { of } from "rxjs/observable/of";
import { delay } from "rxjs/operators";

fakeObservable = of('dummy').pipe(delay(5000));

W RxJS 6+

import { of } from "rxjs";
import { delay } from "rxjs/operators";

fakeObservable = of('dummy').pipe(delay(5000));

Jeśli chcesz opóźnić każdą emitowaną wartość, spróbuj

from([1, 2, 3]).pipe(concatMap(item => of(item).pipe(delay(1000))));

4
Najczystsze moim zdaniem rozwiązanie.
Maayao

To „rozwiązanie” działa tylko wtedy, gdy emitujesz jeden przedmiot. Operator opóźnienia nie jest wywoływany dla każdego elementu w obserwowalnym. Dlatego wymagane jest okropne rozwiązanie concatMap.
Rick O'Shea

1
@ RickO'Shea, pytanie dotyczy jednej emitowanej wartości, dlatego to rozwiązanie.
Adrian Ber

1
Tak świeży i czysty!
Nahn

Zaktualizowałem moją odpowiedź na wiele opóźnień @ RickO'Shea
Adrian Ber

12

To, czego chcesz, to minutnik:

// RxJS v6+
import { timer } from 'rxjs';

//emit [1, 2, 3] after 1 second.
const source = timer(1000).map(([1, 2, 3]);
//output: [1, 2, 3]
const subscribe = source.subscribe(val => console.log(val));

3
Dobra odpowiedź, nie zapomnij zrezygnować z subskrypcji
Sami

8

Trochę za późno na odpowiedź ... ale na wszelki wypadek może ktoś wróci do tego pytania w poszukiwaniu odpowiedzi

„opóźnienie” jest właściwością (funkcją) obserwowalnego

fakeObservable = Observable.create(obs => {
  obs.next([1, 2, 3]);
  obs.complete();
}).delay(3000);

To zadziałało dla mnie ...


1
import 'rxjs/add/operator/delay' wyświetla ten błąd teraz: Nie znaleziono modułu: Błąd: nie można rozwiązać `` rxjs / add / operator / delay ''
Aggie Jon z 87

Dlaczego miałbyś nazwać cię obserwowalną podróbką, skoro jest całkiem realna? :)
lagoman

0

import * as Rx from 'rxjs/Rx';

Powinniśmy dodać powyższy import, aby kod Blow działał

Let obs = Rx.Observable
    .interval(1000).take(3);

obs.subscribe(value => console.log('Subscriber: ' + value));
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.