Как я могу создать наблюдаемое с задержкой


92

Вопрос

В целях тестирования я создаю Observableобъекты, которые заменяют наблюдаемое, которое будет возвращено фактическим http-вызовом с Http.

Моя наблюдаемая создается с помощью следующего кода:

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

Дело в том, что эта наблюдаемая излучает немедленно. Есть ли способ добавить настраиваемую задержку к его излучению?


Трек

Я пробовал это:

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

Но похоже, что это не работает.



Я пытался цепи .create(...)с , .delay(1000)но это не работа:. Observable_1.Observable.create (...) задержка не является функцией.
— Адриан Брунелат

1
Чего именно вы пытаетесь достичь?
— Günter Zöchbauer

ты подписываешься на наблюдаемое?
— shusson

Подделайте задержку ответа Http с моей собственной наблюдаемой. @shusson да, класс, который я тестирую, вызывает сервис (я пытаюсь высмеять) для наблюдаемого, чтобы подписаться на него.
— Адриан Брунелат

Ответы:


144

Используя следующий импорт:

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

Попробуй это:

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

ОБНОВЛЕНИЕ: RXJS 6

Вышеупомянутое решение больше не работает в более новых версиях RXJS (и, например, angular).

Итак, сценарий таков, что у меня есть массив элементов, которые нужно проверить с помощью API. API принимает только один элемент, и я не хочу убивать API, отправляя все запросы сразу. Так что мне нужен синхронизированный выпуск элементов в потоке Observable с небольшой задержкой между ними.

Используйте следующий импорт:

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

Затем используйте следующий код:

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

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

По сути, он создает новый «отложенный» Observable для каждого элемента в вашем массиве. Вероятно, есть много других способов сделать это, но это сработало для меня и соответствует «новому» формату RXJS.


2
Свойство «of» не существует для типа typeof Observable. Вы импортируете свой Observable с помощью import {Observable} from 'rxjs/Observable';?
— Адриен Брунелат

1
На этой странице: npmjs.com/package/rxjs . Я пришел к выводу, что мне нужно явно импортировать файлы import 'rxjs/add/observable/of';. Вы случайно делаете то же самое? Это все еще странно, так как он не связывается с .delay (...), и он показывает ошибку, когда я пытаюсь rxjs/add/observable/delay...
— Адриен Брунелат

4
должен пытаться of(item.pipe ( delay( 1000 ) ))передать of(item))).pipe(delay(1000)массив дал мне ошибки
— Дон Томас Бойл

1
Вот что у меня сработало с rxjs6: from ([1, 2, 3, 4, 5, 6, 7]). Pipe (concatMap (num => of (num) .pipe (delay (1000)))). подписаться (x => console.log (x));
— Роберт

1
Решение @MikeOne тоже сработало для меня. Печально, что для такого простого дела необходимо так много кода ...
— Codev

103

В RxJS 5+ это можно сделать так

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

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

В RxJS 6+

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

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

Если вы хотите отложить каждое испускаемое значение, попробуйте

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

4
На мой взгляд, самое чистое решение.
— Maayao

Это «решение» работает, только если вы испускаете один элемент. Оператор задержки не вызывается для каждого элемента наблюдаемого. Вот почему требуется ужасное решение concatMap.
— Рик О'Ши,

1
@ RickO'Shea, вопрос касается одного излучаемого значения, поэтому это решение.
— Адриан Бер,

1
Такой свежий и такой чистый!
— Nahn

Я обновил свой ответ на несколько задержек @ RickO'Shea
— Адриан Бер

12

Вам нужен таймер:

// 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
Хороший ответ, не забудьте отказаться от подписки
— Sami

8

Немного поздно отвечать ... но на всякий случай может кто-нибудь вернется к этому вопросу в поисках ответа

«задержка» - это свойство (функция) наблюдаемого

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

Это сработало для меня ...


1
import 'rxjs/add/operator/delay' теперь выдает эту ошибку: Модуль не найден: Ошибка: не удается разрешить 'rxjs / add / operator / delay'
— Агги Джон из 87,

Почему вы назвали себя наблюдаемой фальшивкой, когда это вполне реально? :)
— lagoman

0

import * as Rx from 'rxjs/Rx';

Мы должны добавить указанный выше импорт, чтобы код удара работал

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

obs.subscribe(value => console.log('Subscriber: ' + value));
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.