Saya menemukan beberapa implementasi AuthGuard
s yang digunakan take(1)
. Dalam proyek saya, saya menggunakan first()
.
Apakah keduanya bekerja dengan cara yang sama?
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/first';
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import { CanActivate, Router, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { AngularFire } from 'angularfire2';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private angularFire: AngularFire, private router: Router) { }
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
return this.angularFire.auth.map(
(auth) => {
if (auth) {
this.router.navigate(['/dashboard']);
return false;
} else {
return true;
}
}
).first(); // Just change this to .take(1)
}
}
angular
rxjs
angular2-observables
Karuban
sumber
sumber
first()
dantake()
secara umum sama, yang saya pikir jelas, hanya itufirst()
dantake(1)
itu sama. Saya tidak yakin dari jawaban Anda jika Anda pikir masih ada perbedaan?first()
mengirim pemberitahuan kesalahan sementaratake(1)
tidak akan memancarkan apa pun.first()
. Jika itu keadaan aplikasi yang valid saya akan pergi dengantake(1)
..First()
vs.FirstOrDefault()
(dan kalau dipikir-pikir juga.Take(1)
dalam hal itu. Pertama membutuhkan sesuatu dalam koleksi dan memberikan kesalahan untuk koleksi kosong - dan keduanyaFirstOrDefault()
dan.Take(1)
memungkinkan koleksi menjadi kosong dan kembalinull
dan koleksi kosong masing-masing.Kiat: Hanya gunakan
first()
jika:Jika tidak ada emisi dan Anda tidak secara eksplisit menanganinya (dengan
catchError
) maka kesalahan itu akan diperbanyak, mungkin menyebabkan masalah yang tidak terduga di tempat lain dan mungkin cukup sulit untuk dilacak - terutama jika itu berasal dari pengguna akhir.Anda lebih aman menggunakan
take(1)
sebagian besar asalkan:take(1)
tidak memancarkan apa pun jika sumbernya selesai tanpa emisi.first(x => x > 10)
)Catatan: Anda dapat menggunakan predikat dengan
take(1)
seperti ini:.pipe( filter(x => x > 10), take(1) )
. Tidak ada kesalahan dengan ini jika tidak ada yang lebih besar dari 10.Bagaimana dengan
single()
Jika Anda ingin menjadi lebih ketat, dan melarang dua emisi Anda dapat menggunakan
single()
kesalahan mana jika ada nol atau 2+ emisi . Sekali lagi Anda harus menangani kesalahan dalam kasus itu.Kiat:
Single
sesekali dapat bermanfaat jika Anda ingin memastikan rantai yang dapat diamati tidak melakukan pekerjaan ekstra seperti memanggil layanan http dua kali dan memancarkan dua yang dapat diamati. Menambahkansingle
ke ujung pipa akan memberi tahu Anda jika Anda melakukan kesalahan seperti itu. Saya menggunakannya di 'pelari tugas' di mana Anda lulus dalam tugas yang bisa diamati yang seharusnya hanya memancarkan satu nilai, jadi saya meneruskan responsnyasingle(), catchError()
untuk menjamin perilaku yang baik.Kenapa tidak selalu menggunakan
first()
bukantake(1)
?alias. Bagaimana bisa
first
berpotensi menyebabkan lebih banyak kesalahan?Jika Anda memiliki sesuatu yang dapat diobservasi yang mengambil sesuatu dari sebuah layanan dan kemudian mengirimkannya melalui
first()
Anda, Anda akan baik-baik saja. Tetapi jika seseorang datang untuk menonaktifkan layanan untuk alasan apa pun - dan mengubahnya untuk dipancarkanof(null)
atauNEVER
kemudianfirst()
operator hilir akan mulai melempar kesalahan.Sekarang saya menyadari bahwa mungkin itulah yang Anda inginkan - karenanya mengapa ini hanyalah tip. Operator
first
menarik saya karena kedengarannya sedikit kurang 'canggung' daripadatake(1)
tetapi Anda harus berhati-hati dalam menangani kesalahan jika ada kemungkinan sumber tidak memancarkan. Akan sepenuhnya tergantung pada apa yang Anda lakukan.Jika Anda memiliki nilai default (konstan):
Pertimbangkan juga
.pipe(defaultIfEmpty(42), first())
jika Anda memiliki nilai default yang harus digunakan jika tidak ada yang dipancarkan. Ini tentu saja tidak akan menimbulkan kesalahan karenafirst
akan selalu menerima nilai.Catatan yang
defaultIfEmpty
hanya dipicu jika aliran kosong, bukan jika nilai dari apa yang dipancarkannull
.sumber
single
memiliki lebih banyak perbedaanfirst
. 1. Ini hanya akan memancarkan nilaicomplete
. Ini berarti bahwa jika yang diobservasi memancarkan nilai tetapi tidak pernah selesai maka tunggal tidak akan pernah memancarkan nilai. 2. Untuk beberapa alasan jika Anda melewatkan fungsi filtersingle
yang tidak cocok dengan apa pun, itu akan mengeluarkanundefined
nilai jika urutan asli tidak kosong, yang tidak demikian halnyafirst
.Berikut adalah tiga diamati
A
,B
danC
dengan diagram marmer untuk mengeksplorasi perbedaan antarafirst
,take
dansingle
operator:* Legenda : penyelesaian kesalahan
--o--
nilai----!
----|
Mainkan dengan itu di https://thinkrx.io/rxjs/first-vs-take-vs-single/ .
Sudah memiliki semua jawaban, saya ingin menambahkan penjelasan yang lebih visual
Semoga ini bisa membantu seseorang
sumber
Ada satu perbedaan yang sangat penting yang tidak disebutkan di mana pun.
ambil (1) emisi 1, selesai, berhenti berlangganan
first () memancarkan 1, selesai, tetapi tidak berhenti berlangganan.
Ini berarti bahwa upstream Anda yang diamati masih akan menjadi panas setelah pertama () yang mungkin bukan perilaku yang diharapkan.
UPD: Ini mengacu pada RxJS 5.2.0. Masalah ini mungkin sudah diperbaiki.
sumber
Tampaknya dalam RxJS 5.2.0
.first()
operator memiliki bug ,Karena bug itu
.take(1)
dan.first()
dapat berperilaku sangat berbeda jika Anda menggunakannyaswitchMap
:Dengan
take(1)
Anda akan mendapatkan perilaku seperti yang diharapkan:Tetapi dengan
.first()
Anda akan mendapatkan perilaku yang salah:Berikut ini tautan ke codepen
sumber