Kar*_*ban 90 rxjs angular2-observables angular
我发现使用Auth Guards的实现很少AuthGuard.在我的项目中,我曾经take(1)满足我的需求.它的工作方式是否相同?或者其中一个可能有优势.
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)
}
}
Run Code Online (Sandbox Code Playgroud)
mar*_*tin 135
经营者first()和take(1)不一样.
的first()操作者有一个可选的predicate功能性并发射error时,当源完成匹配没有值通知.
例如,这将发出错误:
import { EMPTY, range } from 'rxjs';
import { first, take } from 'rxjs/operators';
EMPTY.pipe(
first(),
).subscribe(console.log, err => console.log('Error', err));
Run Code Online (Sandbox Code Playgroud)
......以及这个:
range(1, 5).pipe(
first(val => val > 6),
).subscribe(console.log, err => console.log('Error', err));
Run Code Online (Sandbox Code Playgroud)
虽然这将匹配发出的第一个值:
range(1, 5).pipe(
first(),
).subscribe(console.log, err => console.log('Error', err));
Run Code Online (Sandbox Code Playgroud)
另一方面,take(1)只取第一个值并完成.没有进一步的逻辑.
range(1, 5).pipe(
take(1),
).subscribe(console.log, err => console.log('Error', err));
Run Code Online (Sandbox Code Playgroud)
然后使用空源Observable它不会发出任何错误:
EMPTY.pipe(
take(1),
).subscribe(console.log, err => console.log('Error', err));
Run Code Online (Sandbox Code Playgroud)
2019年1月:更新了RxJS 6
Sim*_*ver 21
first():如果排放为零,并且您没有明确地使用进行处理,catchError则该错误将被传播,可能在其他地方引起意外问题,并且很难追踪-特别是如果它来自最终用户。
在大多数情况下,您可以安全使用take(1):
take(1)如果源代码完整无发射,则可以不发射任何东西。first(x => x > 10))注意:可以使用带有take(1)这样的谓词:.pipe( filter(x => x > 10), take(1) )。如果没有大于10的值,则没有错误。
single()如果您想要更严格,并且禁止两次发射,则可以使用零或2+发射时的single()哪些误差。同样,在这种情况下,您需要处理错误。
提示:Single如果您想确保可观察链不会做额外的工作(例如两次调用http服务并发出两个可观察物),可能会很有用。添加single到管道的末尾将使您知道是否犯了这样的错误。我在“任务运行器”中使用它,您在其中传递了一个仅可发出一个值的可观察任务,因此我通过响应single(), catchError()以确保行为良好。
first()代替take(1)?又名 如何first 可能导致更多错误?
如果您有一个可观察对象,它可以从服务中获取某些东西,然后通过管道将其通过first()您的大部分时间都可以。但是,如果有人出于某种原因来禁用该服务-并将其更改为发出of(null),NEVER则任何下游first()操作员都将开始抛出错误。
现在,我意识到这可能正是您想要的-因此,这只是一个提示。操作员first之所以向我求助,是因为它听起来比“笨拙”的要少一些,take(1)但是如果有可能源不发光,则您需要小心处理错误。完全取决于您在做什么。
还考虑.pipe(defaultIfEmpty(42), first())是否具有默认值,如果没有发出任何值,则应使用该默认值。当然,这不会引发错误,因为它first总是会收到一个值。
请注意,defaultIfEmpty仅在流为空时才触发,而在发出的值是时才触发null。
kos*_*kos 11
这里有三个观测量A,B以及C用大理石图表探索之间的差异 first,take以及single运营商:
* 图例:
--o-- 值
----! 错误
----| 完成
在https://thinkrx.io/rxjs/first-vs-take-vs-single/上玩。
已经有了所有答案,我想添加一个更直观的解释
希望对别人有帮助
Kam*_*tti 11
事实证明,这两种方法之间有一个非常重要的区别:如果流在发出值之前完成,则first()将发出错误。或者,如果您提供了谓词(i.e. first(value => value === 'foo')),则如果流在发出传递谓词的值之前完成,它将发出错误。
另一方面,如果从未从流中发出值,则take(1)会很高兴地继续执行。这是一个简单的例子:
const subject$ = new Subject();
// logs "no elements in sequence" when the subject completes
subject$.first().subscribe(null, (err) => console.log(err.message));
// never does anything
subject$.take(1).subscribe(console.log);
subject$.complete();
Run Code Online (Sandbox Code Playgroud)
另一个例子,使用谓词:
const observable$ = of(1, 2, 3);
// logs "no elements in sequence" when the observable completes
observable$
.first((value) => value > 5)
.subscribe(null, (err) => console.log(err.message));
// the above can also be written like this, and will never do
// anything because the filter predicate will never return true
observable$
.filter((value) => value > 5);
.take(1)
.subscribe(console.log);
Run Code Online (Sandbox Code Playgroud)
作为 RxJS 的新手,这种行为让我感到非常困惑,尽管这是我自己的错,因为我做了一些错误的假设。如果我费心检查文档,我会发现该行为有明确的记录:
defaultValue如果未提供且未找到匹配元素,则会引发错误。
我经常遇到这种情况的原因是一个相当常见的 Angular 2 模式,其中可观察量在OnDestroy生命周期挂钩期间手动清理:
class MyComponent implements OnInit, OnDestroy {
private stream$: Subject = someDelayedStream();
private destroy$ = new Subject();
ngOnInit() {
this.stream$
.takeUntil(this.destroy$)
.first()
.subscribe(doSomething);
}
ngOnDestroy() {
this.destroy$.next(true);
}
}
Run Code Online (Sandbox Code Playgroud)
该代码乍一看似乎无害,但当之前被销毁的组件stream$可以发出值时,就会出现问题。因为我使用的是first(),所以当组件被销毁时会抛出错误。我通常只订阅流来获取要在组件内使用的值,因此我不关心组件是否在流发出之前被销毁。正因为如此,我开始take(1)在几乎所有我以前使用过的地方使用first().
filter(fn).take(1)比 更详细一点first(fn),但在大多数情况下,我更喜欢更详细一点,而不是处理最终对应用程序没有影响的错误。
还需要注意的是:这同样适用于last()和takeLast(1)。
有一个非常重要的区别,在任何地方都没有提到.
take(1)发出1,完成,取消订阅
first()发出1,完成,但不取消订阅.
这意味着你的上游observable在first()之后仍然会很热,这可能不是预期的行为.
UPD:这是对RxJS 5.2.0的引用.此问题可能已得到修复.
似乎在RxJS 5.2.0中.first()运算符有一个bug,
因为这个bug .take(1),.first()如果你使用它们可能会表现得完全不同switchMap:
随着take(1)你将获得预期的行为:
var x = Rx.Observable.interval(1000)
.do( x=> console.log("One"))
.take(1)
.switchMap(x => Rx.Observable.interval(1000))
.do( x=> console.log("Two"))
.subscribe((x) => {})
// In the console you will see:
// One
// Two
// Two
// Two
// Two
// etc...
Run Code Online (Sandbox Code Playgroud)
但是.first()你会得到错误的行为:
var x = Rx.Observable.interval(1000)
.do( x=> console.log("One"))
.first()
.switchMap(x => Rx.Observable.interval(1000))
.do( x=> console.log("Two"))
.subscribe((x) => {})
// In console you will see:
// One
// One
// Two
// One
// Two
// One
// etc...
Run Code Online (Sandbox Code Playgroud)
这是codepen的链接
| 归档时间: |
|
| 查看次数: |
69531 次 |
| 最近记录: |