Bagaimana saya bisa membuat observable dengan penundaan

92

Pertanyaan

Untuk tujuan pengujian, saya membuat Observableobjek yang menggantikan observable yang akan dikembalikan oleh panggilan http yang sebenarnya dengan Http.

Observable saya dibuat dengan kode berikut:

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

Masalahnya, yang dapat diamati ini memancarkan dengan segera. Apakah ada cara untuk menambahkan penundaan khusus pada emisinya?


Jalur

Saya mencoba ini:

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

Tapi sepertinya tidak berhasil.

Adrien Brunelat
sumber
Saya mencoba untuk menghubungkan .create(...)dengan .delay(1000)tetapi tidak berhasil: Observable_1.Observable.create (...). Delay bukanlah sebuah fungsi.
Adrien Brunelat
1
Apa sebenarnya yang ingin Anda capai?
Günter Zöchbauer
apakah Anda berlangganan observable?
shusson
Palsu penundaan respons Http dengan pengamatan saya sendiri. @shusson ya, kelas yang saya uji memanggil layanan (saya mencoba mengejek) untuk yang dapat diamati untuk berlangganan.
Adrien Brunelat

Jawaban:

144

Menggunakan impor berikut:

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

Coba ini:

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

PEMBARUAN: RXJS 6

Solusi di atas tidak benar-benar berfungsi lagi di versi RXJS yang lebih baru (dan sudut misalnya).

Jadi skenarionya adalah bahwa saya memiliki serangkaian item untuk diperiksa dengan API. API hanya menerima satu item, dan saya tidak ingin menghentikan API dengan mengirim semua permintaan sekaligus. Jadi saya perlu rilis item yang diatur waktunya di aliran Observable dengan sedikit penundaan di antaranya.

Gunakan impor berikut:

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

Kemudian gunakan kode berikut:

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

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

Ini pada dasarnya menciptakan Observable 'tertunda' baru untuk setiap item dalam array Anda. Mungkin ada banyak cara lain untuk melakukannya, tetapi ini berfungsi dengan baik untuk saya, dan sesuai dengan format RXJS 'baru'.

MikeOne
sumber
2
Properti 'dari' tidak ada pada tipe 'typeof Observable'. Apakah Anda mengimpor Observable with Anda import {Observable} from 'rxjs/Observable';?
Adrien Brunelat
1
Dari halaman ini: npmjs.com/package/rxjs . Saya menyimpulkan bahwa saya harus mengimpor secara eksplisit import 'rxjs/add/observable/of';. Apakah Anda kebetulan melakukan hal yang sama? Ini masih aneh, karena tidak akan dirantai dengan .delay (...) dan itu menunjukkan kesalahan ketika saya mencoba rxjs/add/observable/delay...
Adrien Brunelat
4
harus of(item.pipe ( delay( 1000 ) ))harus of(item))).pipe(delay(1000)mencoba untuk pipa array memberi saya kesalahan
Don Thomas Boyle
1
Inilah yang berhasil untuk saya dengan rxjs6: from ([1, 2, 3, 4, 5, 6, 7]). Pipe (concatMap (num => of (num) .pipe (delay (1000)))). berlangganan (x => console.log (x));
robert
1
Solusi @MikeOne juga berhasil untuk saya. Sedih karena begitu banyak kode diperlukan untuk masalah sederhana seperti itu ...
Codev
103

Di RxJS 5+ Anda dapat melakukannya seperti ini

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

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

Di RxJS 6+

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

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

Jika Anda ingin menunda setiap nilai yang dipancarkan coba

from([1, 2, 3]).pipe(concatMap(item => of(item).pipe(delay(1000))));
Adrian Ber
sumber
4
Solusi terbersih menurut saya.
Maayao
"Solusi" ini hanya berfungsi jika Anda mengeluarkan satu item. Operator penundaan tidak dipanggil untuk setiap elemen dalam sebuah observable. Itulah mengapa solusi concatMap yang mengerikan diperlukan.
Rick O'Shea
1
@ RickO'Shea, pertanyaannya adalah tentang satu nilai yang dipancarkan, jadi itulah mengapa solusi ini.
Adrian Ber
1
Sangat segar dan sangat bersih!
Nahn
Saya memperbarui jawaban saya untuk beberapa penundaan @ RickO'Shea
Adrian Ber
12

Yang Anda inginkan adalah pengatur waktu:

// 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
sumber
3
Jawaban bagus, jangan lupa berhenti berlangganan
Sami
8

Agak terlambat untuk menjawab ... tetapi untuk berjaga-jaga mungkin seseorang kembali ke pertanyaan ini mencari jawaban

'delay' adalah properti (fungsi) dari sebuah Observable

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

Ini berhasil untuk saya ...

microchip78
sumber
1
import 'rxjs/add/operator/delay' memberikan kesalahan ini sekarang: Modul tidak ditemukan: Kesalahan: Tidak dapat menyelesaikan 'rxjs / add / operator / delay'
Aggie Jon dari 87
Mengapa Anda menyebut Anda palsu yang bisa diamati padahal itu cukup nyata? :)
lagoman
0

import * as Rx from 'rxjs/Rx';

Kita harus menambahkan impor di atas untuk membuat kode pukulan berfungsi

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

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