Encontré algunas implementaciones de AuthGuard
s que usan take(1)
. En mi proyecto, solía first()
.
¿Ambos funcionan de la misma manera?
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
fuente
fuente
first()
ytake()
son lo mismo en general, lo cual creo que es obvio, solo esofirst()
ytake(1)
son lo mismo. No estoy seguro de su respuesta si cree que todavía hay una diferencia.first()
envíe una notificación de error mientras quetake(1)
simplemente no emitirá nada.first()
. Si es un estado de aplicación válido, iría contake(1)
..First()
vs.FirstOrDefault()
(y ahora que lo pienso también,.Take(1)
Primero requiere algo en la colección y da un error para una colección vacía, y ambos,FirstOrDefault()
y.Take(1)
permite que la colección esté vacía y devuelvanull
y la colección vacía, respectivamente.Consejo: Úselo solo
first()
si:Si hay cero emisiones y no lo está manejando explícitamente (con
catchError
), entonces ese error se propagará, posiblemente causará un problema inesperado en otro lugar y puede ser bastante difícil de rastrear, especialmente si proviene de un usuario final.Estás más seguro usando
take(1)
la mayor parte siempre que:take(1)
no emitir nada si la fuente se completa sin una emisión.first(x => x > 10)
)Nota: Se puede utilizar un predicado con
take(1)
este aspecto:.pipe( filter(x => x > 10), take(1) )
. No hay ningún error con esto si nada es mayor que 10.Qué pasa
single()
Si desea ser aún más estricto y no permitir dos emisiones, puede usar
single()
qué errores si hay cero o más de 2 emisiones . Nuevamente, necesitaría manejar los errores en ese caso.Consejo:
Single
ocasionalmente puede ser útil si desea asegurarse de que su cadena observable no esté haciendo un trabajo adicional, como llamar a un servicio http dos veces y emitir dos observables. Agregarsingle
al final de la tubería le permitirá saber si cometió tal error. Lo estoy usando en un 'corredor de tareas' donde pasas una tarea observable que solo debería emitir un valor, así que paso la respuestasingle(), catchError()
para garantizar un buen comportamiento.¿Por qué no usar siempre en
first()
lugar detake(1)
?aka. ¿Cómo puede
first
potencialmente causar más errores?Si tiene un observable que toma algo de un servicio y luego lo canaliza,
first()
debería estar bien la mayor parte del tiempo. Pero si alguien viene a deshabilitar el servicio por cualquier razón, y lo cambia para emitirof(null)
oNEVER
cualquierfirst()
operador posterior comenzaría a arrojar errores.Ahora me doy cuenta de que podría ser exactamente lo que quieres, de ahí que esto sea solo un consejo. El operador
first
me atrajo porque sonaba un poco menos `` torpe '' que,take(1)
pero debes tener cuidado con el manejo de errores si alguna vez existe la posibilidad de que la fuente no se emita. Sin embargo, dependerá completamente de lo que estés haciendo.Si tiene un valor predeterminado (constante):
Considere también
.pipe(defaultIfEmpty(42), first())
si tiene un valor predeterminado que debe usarse si no se emite nada. Por supuesto, esto no generaría un error porquefirst
siempre recibiría un valor.Tenga en cuenta que
defaultIfEmpty
solo se activa si la secuencia está vacía, no si el valor de lo que se emite esnull
.fuente
single
tiene más diferencias confirst
. 1. Solo emitirá el valor encomplete
. Esto significa que si el observable emite un valor pero nunca se completa, single nunca emitirá un valor. 2. Por alguna razón, si pasa una función de filtrosingle
que no coincide con nada, emitirá unundefined
valor si la secuencia original no está vacía, que no es el casofirst
.Aquí hay tres observables
A
,B
yC
con los diagramas de mármol para explorar la diferencia entrefirst
,take
ysingle
los operadores:* Leyenda :
--o--
valor de----!
error----|
completadoJuega con él en https://thinkrx.io/rxjs/first-vs-take-vs-single/ .
Ya teniendo todas las respuestas, quería agregar una explicación más visual.
Espero que ayude a alguien
fuente
Hay una diferencia realmente importante que no se menciona en ninguna parte.
take (1) emite 1, completa, cancela la suscripción
first () emite 1, completa, pero no se da de baja.
Significa que su observable aguas arriba todavía estará caliente después de first (), lo que probablemente no sea un comportamiento esperado.
UPD: Esto se refiere a RxJS 5.2.0. Este problema podría estar ya solucionado.
fuente
Parece que en RxJS 5.2.0 el
.first()
operador tiene un error ,Debido a ese error
.take(1)
y.first()
puede comportarse de manera bastante diferente si los está usando conswitchMap
:Con
take(1)
usted obtendrá un comportamiento como se esperaba:Pero con
.first()
usted obtendrá un comportamiento incorrecto:Aquí hay un enlace a codepen
fuente