121 votes

Comment puis-je créer une observable avec un délai ?

Pregunta

À des fins de test, je crée Observable qui remplacent l'observable qui serait renvoyé par un appel http réel par des objets Http .

Mon observable est créé avec le code suivant :

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

Le truc, c'est que cet observable émet immédiatement. Existe-t-il un moyen d'ajouter un délai personnalisé à son émission ?


Piste

J'ai essayé ça :

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

Mais ça ne semble pas fonctionner.

0 votes

J'ai essayé d'enchaîner .create(...) avec .delay(1000) mais ça n'a pas marché : Observable_1.Observable.create(...).delay n'est pas une fonction.

1 votes

Qu'essayez-vous exactement d'accomplir ?

185voto

MikeOne Points 2302

En utilisant les importations suivantes :

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

Essayez ça :

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

MISE À JOUR : RXJS 6

La solution ci-dessus ne fonctionne plus vraiment dans les nouvelles versions de RXJS (et d'angular par exemple).

Le scénario est donc le suivant : j'ai un tableau d'éléments à vérifier avec une API. L'API n'accepte qu'un seul élément, et je ne veux pas tuer l'API en envoyant toutes les requêtes en même temps. J'ai donc besoin d'une libération minutée des éléments sur le flux Observable avec un petit délai entre les deux.

Utilisez les importations suivantes :

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

Utilisez ensuite le code suivant :

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

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

Il crée essentiellement un nouvel Observable 'retardé' pour chaque élément de votre tableau. Il y a probablement beaucoup d'autres façons de faire, mais celle-ci a bien fonctionné pour moi, et est conforme au 'nouveau' format RXJS.

2 votes

La propriété 'of' n'existe pas sur le type 'typeof Observable'. Importez-vous votre Observable avec import {Observable} from 'rxjs/Observable'; ?

0 votes

Oui, j'utilise beaucoup .of, donc je suppose qu'il y a quelque chose d'étrange dans vos dépendances rx.

0 votes

Je veux dire que tu confirmes que tu n'importes pas avec import {Observable} from 'rxjs' ? Si oui, j'ai quelques recherches à faire...

132voto

Adrian Ber Points 1829

Dans RxJS 5+ vous pouvez le faire comme ceci

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

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

Dans RxJS 6+

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

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

Si vous voulez retarder chaque valeur émise, essayez

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

4 votes

La solution la plus propre à mon avis.

0 votes

Cette "solution" ne fonctionne que si vous émettez un seul élément. L'opérateur de retardement n'est pas invoqué pour chaque élément d'une observable. C'est pourquoi l'horrible solution concatMap est nécessaire.

1 votes

@RickO'Shea, la question porte sur une valeur émise, d'où cette solution.

15voto

Pellet Points 106

Ce que vous voulez, c'est un minuteur :

// 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));

5 votes

Bonne réponse, n'oubliez pas de vous désabonner.

1 votes

@Sami cette instance spécifique de timer n'a pas besoin d'être désabonné (il se désabonnera automatiquement après 1 seconde). Ceci est dû au fait que timer n'utilise pas le second argument de l'intervalle, ce qui nécessiterait un code supplémentaire pour indiquer qu'il a été complété d'une manière ou d'une autre.

8voto

microchip78 Points 1426

Il est un peu tard pour répondre ... mais juste au cas où quelqu'un reviendrait sur cette question pour y trouver une réponse.

delay' est la propriété (fonction) d'un Observable.

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

Cela a marché pour moi...

1 votes

import 'rxjs/add/operator/delay' donne cette erreur maintenant : Module non trouvé : Erreur : Impossible de résoudre 'rxjs/add/operator/delay'.

1 votes

Pourquoi qualifier votre observable de faux alors qu'il est tout à fait réel ? :)

-1voto

*`import as Rx from 'rxjs/Rx';`**

Nous devrions ajouter l'import ci-dessus pour que le code du coup fonctionne.

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

obs.subscribe(value => console.log('Subscriber: ' + value));

0 votes

Import * est un peu exagéré pour cette simple tâche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X