Angular2 查询参数订阅触发两次 [英] Angular2 Query Params Subscription Fires Twice
问题描述
尝试处理 OAuth 登录场景,如果用户登陆查询字符串中带有 authorization_code
的页面,我们会处理令牌并继续或如果他们登陆如果页面没有那个,我们会检查本地存储中是否存在现有令牌,确保它仍然有效,并根据其有效性重定向到登录或继续.
Trying to handle an OAuth login scenario where if the user lands on a page with authorization_code
in the query string, we process the token and continue or if they land on the page without that, we check local storage for their existing token, make sure it's still valid and either redirect to login or continue, based on its validity.
问题在于,在我们检查 authorization_code
查询字符串参数是否存在的地方,订阅被触发两次.第一次它是空的,第二次它在字典中有正确的值.
The problem is that where we're checking for the existence of the authorization_code
query string param, the subscription is firing twice. The first time it is empty, the second time it has the correct value in the dictionary.
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);
});
}
}
此代码输出:
Plunker(您需要将其弹出到新窗口并添加查询字符串 ?test=test
).
Plunker (you'll need to pop it out into a new window and add a query string ?test=test
).
问题
- 是不是我做错了什么让它触发了两次?
- 我不能只是忽略带有条件的空对象,因为在这种情况下我们需要验证现有的身份验证令牌——是否有另一种方法来解决这个问题,而不是完全破解?
推荐答案
Router observables (as another answer提到) 是 BehaviorSubject
主题,它们不同于常规的 RxJS Subject
或Angular 2 EventEmitter
因为它们将初始值推送到序列(在 queryParams
的情况下为空对象).
Router observables (as another answer mentions) are BehaviorSubject
subjects, they differ from regular RxJS Subject
or Angular 2 EventEmitter
in that they have the initial value pushed to the sequence (an empty object in the case of queryParams
).
一般来说,订阅初始化逻辑的可能性是可取的.
Generally the possibility of subscribing with initialization logic is desirable.
可以用skip
操作符跳过初始值.
The initial value can be skipped with skip
operator.
this._route.queryParams
.skip(1)
.subscribe(params => ...);
但更自然的处理方法是过滤掉所有不相关的参数(初始 params
属于这一类).还可以使用 distinctUntilChanged
运算符过滤重复的 authorization_code
值,以避免对后端进行不必要的调用.
But more natural way to handle this is to filter out all irrelevant params (initial params
falls into this category). Duplicate authorization_code
values can also be filtered with distinctUntilChanged
operator to avoid unnecessary calls to the backend.
this._route.queryParams
.filter(params => 'authorization_code' in params)
.map(params => params.authorization_code)
.distinctUntilChanged()
.subscribe(authCode => ...);
请注意,Angular 2 导入了有限数量的 RxJS 操作符(至少在 @angular/router
的情况下是 map
).如果未使用完整的 rxjs/Rx
包,则可能需要导入正在使用的额外运算符(filter
、distinctUntilChanged
)import 'rxjs/add/operator/
.
Notice that Angular 2 imports a limited amount of RxJS operators (at least map
in the case of @angular/router
). If full rxjs/Rx
bundle isn't used, it may be necessary to import extra operators (filter
, distinctUntilChanged
) that are in use with import 'rxjs/add/operator/<operator_name>'
.
这篇关于Angular2 查询参数订阅触发两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!