luk*_*fer 25 rxjs angular2-routing angular
尝试处理OAuth登录场景,如果用户登陆authorization_code查询字符串中的页面,我们处理令牌并继续,或者如果他们没有那个登陆页面,我们检查本地存储是否有他们现有的令牌,确保它仍然是有效,并根据其有效性重定向登录或继续.
问题是,在我们检查authorization_code查询字符串参数是否存在的情况下,订阅会触发两次.第一次它是空的,第二次它在字典中具有正确的值.
app.component.ts
export class App implements OnInit {
constructor(private _router: ActivatedRoute) {
}
public ngOnInit(): void {
console.log('INIT');
this._route.queryParams.subscribe(params => {
console.log(params);
});
}
}
Run Code Online (Sandbox Code Playgroud)
Plunker(你需要将它弹出到一个新窗口并添加一个查询字符串?test=test).
问题
Est*_*ask 19
路由器可观察量(作为另一个答案提及)是BehaviorSubject主题,它们与常规RxJS Subject或Angular 2的不同之处EventEmitter在于它们具有推送到序列的初始值(在该情况下为空对象queryParams).
通常,期望订阅初始化逻辑的可能性.
skip操作员可以跳过初始值.
this._route.queryParams
.skip(1)
.subscribe(params => ...);
Run Code Online (Sandbox Code Playgroud)
但更自然的方法是过滤掉所有不相关的参数(初始params属于这一类).authorization_code也可以使用distinctUntilChanged运算符过滤重复值,以避免对后端进行不必要的调用.
this._route.queryParams
.filter(params => 'authorization_code' in params)
.map(params => params.authorization_code)
.distinctUntilChanged()
.subscribe(authCode => ...);
Run Code Online (Sandbox Code Playgroud)
请注意,Angular 2导入有限数量的RxJS运算符(至少map在这种情况下@angular/router).如果rxjs/Rx未使用完整捆绑包,则可能需要导入正在使用的额外运算符(filter,distinctUntilChanged)import 'rxjs/add/operator/<operator_name>'.
解决此问题的最佳方法是订阅路由器事件,并仅在路由被勾选到navigated状态后处理查询参数:
public doSomethingWithQueryParams(): Observable<any> {
let observer: Observer<any>;
const observable = new Observable(obs => observer = obs);
this.router.events.subscribe(evt => {
// this is an injected Router instance
if (this.router.navigated) {
Observable.from(this.activatedRoute.queryParams)
// some more processing here
.subscribe(json => {
observer.next(json);
observer.complete();
});
}
});
return observable;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
您可以等到 NavigationEnd 事件完成,然后获取值或订阅更改:
constructor(private router: Router, private route: ActivatedRoute) { }
public ngOnInit(): void {
console.log('INIT');
this.router.events
.subscribe((event) => {
if (event instanceof NavigationEnd) {
// Get a good value
let initialParams = this.route.snapshot.queryParams;
console.log(initialParams);
// or subscribe for more changes
this.route.queryParams.subscribe(params => {
console.log(params);
});
}
});
}
Run Code Online (Sandbox Code Playgroud)
以防万一有人正在寻找解决方案,我找到了一个效果很好的解决方法。我提出的解决方案仅涉及对NavigationEndRouter 实例的事件进行订阅。
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(
private route: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
this.router.events
.subscribe(e => {
if (e.constructor.name === 'NavigationEnd' && this.router.navigated) {
this.route.queryParams
.subscribe(params => {
// do something
})
.unsubscribe();
}
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8274 次 |
| 最近记录: |