Unterschied zwischen .unsubscribe to .take (1)

72

Ich frage mich, ob es einen Unterschied in der Leistung zwischen der Verwendung ist .take(1)und .unsubscribewenn unsubscribewird direkt nach dem Abonnement verwendet:

var observable = Rx.Observable.interval(100);

Zuerst:

var subscription = observable.subscribe(function(value) {
   console.log(value);
}).unsubscribe();

Zweite:

var subscription = observable.take(1).subscribe(function(value) {
    console.log(value);
});

Irgendwelche Ideen dazu machen die Leistung anders?

TheUnreal
quelle
3
var subscription = observable.subscribe({function A}).unsubscribe();funktioniert nicht wie erwartet, falls Funktion A aufgerufen wird, nachdem Javascrit diese Zeile beendet hat. Wenn Sie also nur einen Wert erhalten, erhalten Sie null Werte. Es wird empfohlen, manuell zu abonnieren und take (..) oder andere Methoden wie take zu verwenden, die sich mit dem Abonnement für Sie befassen.
Stav Alfi

Antworten:

126

Jedes dient einem anderen Zweck, daher ist es schwierig, sie zu vergleichen.

Im Allgemeinen, wenn Sie diese Quelle nehmen:

const source = range(1,3);

... und konsumiere es mit subscribe()gefolgt von unsubscribe():

source.subscribe(
  console.log,
  undefined, 
  () => console.log('complete')
).unsubscribe();

... dann werden alle Werte von sourceausgegeben, obwohl wir unsubscribe()direkt nach dem Abonnieren angerufen haben . Dies liegt daran, dass der Code immer noch streng sequentiell (synchron) ist und sourceein kaltes Observable ist.

1
2
3
complete

Übrigens, versuchen Sie, einen delay(0)Operator hinzuzufügen source.pipe(delay(0)).subscribe(...).unsubscribe(). Dies macht das Ausgeben von Werten unter Verwendung eines tatsächlichen setTimeout()Aufrufs asynchron und wird aus diesem Grund unsubscribe()vor allen nextHandlern aufgerufen und sofort verworfen.

Mit anderen Worten unsubscribe(), Sie können jederzeit aufhören, Werte zu empfangen. Auch wenn die Quelle keinen Wert ausgegeben hat (wir erhalten nie eine vollständige Benachrichtigung).

Die Verwendung des take()Operators beschränkt die Kette darauf, nur eine bestimmte Anzahl von Werten auszugeben.

source.pipe(
  take(1),
)
.subscribe(
  console.log,
  undefined,
  () => console.log('complete')
);

Dies gibt nur einen einzigen Wert aus und vervollständigt:

1
complete

Selbst wenn Sie .unsubscribe()das Ergebnis hinzufügen, wäre es das gleiche.

Siehe Live-Demo: https://stackblitz.com/edit/rxjs-tbu5kb

Dies take()gilt auch für einen Operator, während unsubscribe()es sich um eine Methode für ein SubscriptionObjekt handelt. Diese beiden Dinge sind oft austauschbar, aber sie ersetzen sich nie vollständig.

Jan 2019: Aktualisiert für RxJS 6

Martin
quelle
47
hi @martin braucht (1) eine Abmeldung? Wenn ich take (1) hinzufüge, muss ich erneut abbestellen? Danke
fünfter
88
@fifth Nein, das tust du nicht. Wenn die Kette abgeschlossen ist, werden alle Entsorgungshandler rekursiv aufgerufen, sodass Sie sich nicht unsubscribeselbst anrufen müssen .
Martin
7
fünftens, @martin - könnten Sie aus diesen beiden Kommentaren eine Frage und Antwort machen? Ich habe tatsächlich nach dieser speziellen Frage gesucht ("Meldet sich take-1 ab?") Und bin versehentlich auf diese Frage gestoßen. Nach der ungewöhnlich hohen Anzahl an Upvotes zu Ihren Kommentaren zu urteilen, scheinen andere Leute zuzustimmen;) Oder sie zumindest auf sichtbare Weise in die aktuellen Fragen und Antworten aufzunehmen / einzubinden. Die Tatsache, dass take-X (oder eine 'Fertigstellung' eines Streams) sich abmeldet, ist wirklich wichtig, und ich kann keine Fragen und Antworten finden, die diese Angelegenheit berühren und eine endgültige und klare Antwort geben würden, wie Martins Kommentar hier.
Quetzalcoatl
2
@quetzalcoatl Es ruft das Abbestellen auf, wenn Sie den Quellcode sehen. github.com/ReactiveX/rxjs/blob/master/src/internal/operators/…
Tengis
Seien Sie vorsichtig, wenn aus irgendeinem Grund keine (oder eine beliebige Anzahl von Zählungen) erforderlich ist, wird das Abonnement nicht abgebrochen.
Farhad
28

Denken Sie daran, dass take (1) sich immer noch nicht abmeldet, wenn eine Komponente zerstört wird. Das Abonnement bleibt aktiv, bis der erste Wert ausgegeben wird, unabhängig davon, ob die Komponente aktiv oder zerstört ist. Wenn wir also in unserem Abonnement etwas Verrückteres tun, wie den Zugriff auf das DOM, wird möglicherweise ein Fehler in der Konsole angezeigt. https://medium.com/angular-in-depth/the-best-way-to-unsubscribe-rxjs-observable-in-the-angular-applications-d8f9aa42f6a0

el peregrino
quelle
2
Hilfreicher Artikel.
NachtElf91