Wie kann ich ein Observable mit einer Verzögerung erstellen?

92

Frage

Zu Testzwecken erstelle ich ObservableObjekte, die das Observable ersetzen, durch das ein tatsächlicher http-Aufruf zurückgegeben wird Http.

Mein Observable wird mit folgendem Code erstellt:

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

Die Sache ist, dieses beobachtbare strahlt sofort aus. Gibt es eine Möglichkeit, der Emission eine benutzerdefinierte Verzögerung hinzuzufügen?


Spur

Ich habe es versucht:

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

Aber es scheint nicht zu funktionieren.

Adrien Brunelat
quelle
Ich habe versucht, Kette .create(...)mit , .delay(1000)aber es hat nicht funktioniert. Observable_1.Observable.create (...) Verzögerung nicht eine Funktion ist.
Adrien Brunelat
1
Was genau versuchst du zu erreichen?
Günter Zöchbauer
Abonnieren Sie das Observable?
Shusson
Fake die HTTP-Antwortverzögerung mit meiner eigenen beobachtbaren. @shusson Ja, die Klasse, die ich teste, ruft den Dienst (ich versuche mich zu verspotten) für das Observable auf, um es zu abonnieren.
Adrien Brunelat

Antworten:

144

Verwenden der folgenden Importe:

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

Versuche dies:

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

UPDATE: RXJS 6

Die obige Lösung funktioniert in neueren Versionen von RXJS (und beispielsweise von Angular) nicht mehr wirklich.

Das Szenario ist also, dass ich eine Reihe von Elementen habe, mit denen ich eine API überprüfen kann. Die API akzeptiert nur ein einzelnes Element, und ich möchte die API nicht beenden, indem alle Anforderungen gleichzeitig gesendet werden. Daher benötige ich eine zeitgesteuerte Veröffentlichung von Elementen im Observable-Stream mit einer kleinen Verzögerung dazwischen.

Verwenden Sie die folgenden Importe:

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

Verwenden Sie dann den folgenden Code:

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

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

Grundsätzlich wird für jedes Element in Ihrem Array ein neues "verzögertes" Observable erstellt. Es gibt wahrscheinlich viele andere Möglichkeiten, dies zu tun, aber dies hat für mich gut funktioniert und entspricht dem 'neuen' RXJS-Format.

MikeOne
quelle
2
Die Eigenschaft 'von' ist für den Typ 'Typ von Observable' nicht vorhanden. Importieren Sie Ihr Observable mit import {Observable} from 'rxjs/Observable';?
Adrien Brunelat
1
Von dieser Seite: npmjs.com/package/rxjs . Ich folgerte, dass ich explizit mit importieren musste import 'rxjs/add/observable/of';. Tun Sie zufällig das Gleiche? Es ist immer noch seltsam, da es nicht mit .delay (...) verkettet wird und es einen Fehler zeigt, wenn ich es versuche rxjs/add/observable/delay...
Adrien Brunelat
4
sollte of(item.pipe ( delay( 1000 ) ))sein of(item))).pipe(delay(1000)zu Rohr versucht gab das Array mir Fehler
Don Thomas Boyle
1
Dies hat bei mir mit rxjs6 funktioniert: from ([1, 2, 3, 4, 5, 6, 7]). Pipe (concatMap (num => von (num) .pipe (delay (1000))). subscribe (x => console.log (x));
Robert
1
Die Lösung von @MikeOne hat auch bei mir funktioniert. Traurig, dass so viel Code für eine so einfache Sache notwendig ist ...
Codev
103

In RxJS 5+ können Sie dies so tun

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

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

In RxJS 6+

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

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

Wenn Sie jeden ausgegebenen Wert verzögern möchten, versuchen Sie es

from([1, 2, 3]).pipe(concatMap(item => of(item).pipe(delay(1000))));
Adrian Ber
quelle
4
Die sauberste Lösung meiner Meinung nach.
Maayao
Diese "Lösung" funktioniert nur, wenn Sie einen Artikel ausgeben. Der Verzögerungsoperator wird nicht für jedes Element in einem Observable aufgerufen. Deshalb ist die schreckliche concatMap-Lösung erforderlich.
Rick O'Shea
1
@ RickO'Shea, die Frage bezieht sich auf einen emittierten Wert, deshalb diese Lösung.
Adrian Ber
1
So frisch und so sauber!
Nahn
Ich habe meine Antwort für mehrere Verzögerungen @ RickO'Shea
Adrian Ber
12

Was Sie wollen, ist ein Timer:

// 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));
Pellet
quelle
3
Gute Antwort, vergessen Sie nicht, sich abzumelden
Sami
8

Es ist etwas spät zu beantworten ... aber für den Fall, dass jemand zu dieser Frage zurückkehrt und nach einer Antwort sucht

'Verzögerung' ist eine Eigenschaft (Funktion) eines Observable

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

Das hat bei mir funktioniert ...

Mikrochip78
quelle
1
import 'rxjs/add/operator/delay' gibt diesen Fehler jetzt: Modul nicht gefunden: Fehler: 'rxjs / add / operator / delay' kann nicht behoben werden
Aggie Jon vom 87.
Warum würdest du dich als beobachtbare Fälschung bezeichnen, wenn es ziemlich real ist? :)
Lagoman
0

import * as Rx from 'rxjs/Rx';

Wir sollten den obigen Import hinzufügen, damit der Blow-Code funktioniert

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

obs.subscribe(value => console.log('Subscriber: ' + value));
Narendra Kumar Achari
quelle