【问题标题】:Subscription function in Angular 4Angular 4 中的订阅功能
【发布时间】:2018-11-26 07:43:23
【问题描述】:

我有一个关于 observables 和订阅的问题。我正在开发一种方法,当我收到 http 401 状态时,会更新信号并更新函数,但这不起作用并且方法更新函数没有运行

这是带有订阅方式的函数:

 ngOnInit() {

    this.licenceList = new Array<License>();

    this.subscription = this._phpService.tokenRefreshed$.subscribe(value =>{
      if(value === true){
        this._license.getLicenseList().subscribe(licenses => this.licenceList = licenses);
      }
    });

    this._license.getLicenseList().subscribe(licenses => this.licenceList = licenses);

  }

在这里我声明了 observable

private tokenRefreshed: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
tokenRefreshed$  = this.tokenRefreshed.asObservable();

用这个方法我刷新了令牌

interceptMex(message)
{
        switch(message.status){
            case 401:
                ++PhpService.tokenQueue;
                if(PhpService.tokenQueue >  1 ){
                    return message.json();
                }else{
                     this.refreshToken();
                }
            case 404:
                return message.json();
            default:
                return message.json();
        }

}

refreshToken(){
    let url = "auth/refresh/self";
    this.post(url, localStorage.getItem('refresh_token')).subscribe(res =>{
        window.localStorage.setItem('access_token', res['access_token']);
        window.localStorage.setItem('refresh_token', res['refresh_token']);
        this.tokenRefreshed.next(true);
    });

}

更新

发布功能:

post(url, parameters): Observable<any>
    {
        PhpService.layoutService.updatePreloaderState('active');
        PhpService.loaderQueue++;
        let apiDomain = this.config.settings.urlController;

        let phpUrl = apiDomain + url;
        let headers = new Headers({'Content-Type' : 'application/json'});

        if(localStorage.getItem("access_token") != null){
            headers.append('Authorization' ,localStorage.getItem('access_token'));
        }

        return this.http.post(phpUrl, '', {headers: headers, body: parameters})
            .map(message => this.interceptMex(message))
            .catch( error =>  Observable.of( this.interceptMex(error)))
            .finally(() => PhpService.stopLoader());
    }

有人可以帮我吗?

【问题讨论】:

  • 好像根本没有调用interceptMex 方法?看起来 refreshToken 方法只将一个值传递给 tokenRefreshed observable
  • @RudolfOlah 在 post 方法之后调用了 interceptMex 方法,我已经用 post 方法更新了代码
  • @RudolfOlah 检查我的更新

标签: angular typescript rxjs observable subscription


【解决方案1】:

我几乎不知道 rxjs,这可能不是你问题的答案,但我仍然可以指出一些必须是错误的:

您进行的每个 subscribe() 调用都会创建一个新订阅。这意味着每次 tokenRefreshed$ 触发值为 true 时,您都在创建一个新订阅,而无需关注旧订阅;

我认为这样的事情会更有意义:

this.tokenSubscription = this._phpService.tokenRefreshed$.subscribe(value =>{
  if(value === true){     
    this.licenceSubscription.unsubscribe();
    this.licenceSubscription = this._license.getLicenseList().subscribe(licenses => this.licenceList = licenses);
  }
});
this.licenceSubscription = this._license.getLicenseList().subscribe(licenses => this.licenceList = licenses);

由于订阅处理程序是相同的,我也不会重新创建它们:

// This creates the handler once, instead of a new one every time you subscribe.
this.handler = licenses => this.licenceList = licenses; 

this.tokenSubscription = this._phpService.tokenRefreshed$.subscribe(value =>{
  if(value === true){      
     this.licenceSubscription.unsubscribe();
     this.licenceSubscription = this._license.getLicenseList().subscribe(this.handler);
  }
});
this.licenceSubscription = this._license.getLicenseList().subscribe(this.handler);

原因是,如果订阅完全类似于 EventListeners(我知道这是疯狂的假设),那么尝试将现有处理程序添加到订阅将被忽略 - 有效防止泄漏和无意触发多个处理程序。

还有一点很重要:我认为如果你在任何地方都拼写license,你的世界会更轻松。

我认为以上所有内容都与您所询问的问题无关,但请耐心等待以获得真正的答案。 (你可以在一条评论中塞进很多东西,所以我把它变成了一个答案。)

【讨论】:

  • 这可能是真的,但如果 .getLicenseList 是一个 HTTPClient.get(),那么它就是不需要取消订阅的一次性类型。虽然如果它是一个多发射的 observable,那么你是对的(而且,最好还是养成退订的习惯)
  • 啊哈。学习到教训了。我尽量让我的胖手指远离我专业领域之外的事情,但有时我内心的Besserwisser会变得更好。
  • 哈哈。不过还是不错的建议。并感谢'besserwisser'。我绝对需要这个词。
  • @ippi 感谢您的建议,即使这不是解决方案
【解决方案2】:

在您的代码 sn-ps 中似乎没有明显错误。

这似乎是一个更通用的调试问题:

  1. check the documentation for handling errors in Angular
  2. check the docs for how .catch() works with Observables
  3. 在 Web 浏览器的 JavaScript 调试器中插入断点,以确保未调用该方法,或者如果已调用,则逐步确定变量在该点的值
  4. 使用旧的 console.log 方法并将其插入代码中的几个位置以跟踪代码流并查看返回的内容
  5. 检查网络请求以查看响应状态和有效负载;也许您实际上在任何时候都没有收到 401 错误响应?

【讨论】:

    猜你喜欢
    • 2018-11-23
    • 2018-11-26
    • 2018-05-25
    • 2018-08-08
    • 2018-01-13
    • 2018-07-13
    • 2017-11-25
    • 2018-02-01
    • 1970-01-01
    相关资源
    最近更新 更多