Bir defalık abonelik oluştur


182

Observableİlk çağrıldığında hemen atılan bir abonelik oluşturmam gerekiyor .

Gibi bir şey var mı:

observable.subscribeOnce(func);

Benim kullanım durumum, hızlı bir rota işleyicisinde bir abonelik oluşturuyorum ve abonelik istek başına birden çok kez çağrılıyor.

Yanıtlar:


319

İhtiyacınız olan şeyden% 100 emin değilsiniz, ancak yalnızca ilk değeri gözlemlemek istiyorsanız, ya first()da şunu kullanın take(1):

observable.first().subscribe(func);

not: .take(1)ve .first()her ikisi de koşulları karşılandığında otomatik olarak abonelikten çık

RxJS 5.5+ sürümünden güncelleme

Coderer tarafından yapılan yorumdan .

import { first } from 'rxjs/operators'

observable
  .pipe(first())
  .subscribe(func);

İşte nedeni


33
Abonelik sonrasında otomatik olarak temizlenir mi?
Berkeley Martinez

50
Evet öyle. Koşulları karşılandığında aboneliği iptal edin ve her ikisini de kaldırın.
Brandon

20
Belgeler neden aboneliği otomatik olarak attığını söylemiyor?
jzig

17
Gözlemlenebilir bir akış sona erdiğinde aboneliklerin atılması genel bir RxJS kuralıdır. Bu, bir akışı "kısaltan" (veya farklı bir akış türüne dönüştüren) herhangi bir işleç, işlemleri tamamlandığında kaynak akışından aboneliği iptal edeceği anlamına gelir. Bunun belgelerde nerede belirtilip belirtilmediğinden emin değilim.
Brandon

37
2018'de buna kimse geliyorsa, aslında observable.pipe(first()).subscribe(func)nereden firstgeliyor istersiniz rxjs/operators.
Coderer

32

RxJS şimdiye kadar karşılaştığım en iyi belgelere sahip. Körük bağlantısının takip edilmesi sizi operatörler için son derece yararlı bir tablo eşleme kullanım durumlarına götürecektir. Örneğin, altında kullanma durumu "İlk değer almak istiyorum" üç operatör şunlardır: first, firstOrDefaultve sample.

Gözlemlenebilir bir dizi bildirim olmadan tamamlanırsa, firstoperatör abonelere firstOrDefaultvarsayılan bir değer sağlarken operatör aboneleri bir hata ile bilgilendirir .

operatör kullanım senaryosu arama


3

Bir Gözlenebilir'i yalnızca bir kez çağırmak istiyorsanız, bundan bir akış beklemeyeceğiniz anlamına gelir. Abonelik iptali gerekmediği için toPromise()bunun yerine kullanmak subscribe()yeterli olacaktır toPromise().


Çok ilginç, bu da demek biz sadece bunu bir astar yaparawaitpromise
Louie Almeda

@LouieAlmeda bize bir liner örneği verebilir misiniz?
Ado Ren

Merhaba @AdoRen, tekniği sizin için burada bir cevap olarak açıkladım, umarım bu yardımcı olur.
Louie Almeda

2

Tamamlamak için Brandon'ın cevap @ kullanılarak first()ya da benzeri bir güncellenmesi için de önemlidir BehaviorSubjectonun dayalı Observable. Örneğin (denenmemiş):

var subject = new BehaviorSubject({1:'apple',2:'banana'});
var observable = subject.asObservable();

observable
  .pipe(
    first(), // <-- Ensures no stack overflow
    flatMap(function(obj) {
      obj[3] = 'pear';
      return of(obj);
    })
  )
  .subscribe(function(obj) {
    subject.next(obj);
  });

2

Temiz ve Kullanışlı Sürüm

M Fuat NUROĞLU'nun gözlemlenebilir olanı bir vaat haline getirme konusundaki şaşırtıcı cevabına genişleyerek işte bunun çok uygun versiyonu.

const value = await observable.toPromise();

console.log(value)

Bunun güzelliği, başka bir iç içe blok eklemeden bu değeri normal bir değişken gibi kullanabilmemizdir!

Bu, özellikle birden fazla gözlenebilir öğeden birden fazla değer almanız gerektiğinde kullanışlıdır. Düzgün ve temiz.

const content = await contentObservable.toPromise();
const isAuthenticated = await isAuthenticatedObservable.toPromise();

if(isAuthenticated){
   service.foo(content)
}

Tabii ki, asyncbu rota ile gidecek olursanız, içerme işlevinizi yapmanız gerekecektir . Ayrıca .then, içeren işlevin zaman uyumsuz olmasını istemiyorsanız söz verebilirsiniz.

Bu yaklaşımda dengesizlikler olup olmadığından emin değilim, yorumlarda bana bildirmekten çekinmeyin, böylece farkındayız.

PS Bu yanıtı beğendiyseniz, M Fuat NUROĞLU'nun Yanıtı'nı da yükseltmeyi unutmayın :)


0

Benzer bir sorum vardı.

Aşağıda farklı devlet değiştiricilerinden daha sonra çağrılmıştır. İstemediğim gibi.

function foo() {
    // this was called many times which was not needed
    observable.subscribe(func);
    changeObservableState("new value");
}

unsubscribe()Aşağıdaki gibi abone olduktan sonra denemeye karar verdim .

function foo() {
    // this was called ONE TIME
    observable.subscribe(func).unsubscribe();
    changeObservableState("new value");
}

subscribe(func).unsubscribe();gibidir subscribeOnce(func).

Umarım bu da sana yardımcı olmuştur.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.