【问题标题】:Observable is not saving the data when refreshing the page manually手动刷新页面时 Observable 不保存数据
【发布时间】:2018-08-02 12:30:43
【问题描述】:

我的服务构造函数中有这段代码:

this.getUser().subscribe( data => this.user = data.text(), error => console.log(error) );

当使用路由器链接(从菜单)在我的应用程序中导航时,此代码有效,但是当手动刷新页面时... data.text() 包括登录用户(如果我将其打印到控制台,我可以看到它) 但 this.user 变量没有保存它,它仍然是“未定义”!

到目前为止,我尝试使用 setTimeout 或 BehaviorSubject 但没有运气:

private _subject = new BehaviorSubject<any>([]);
subject$ = this._subject.asObservable();
this.getUser().subscribe( data => 
        //setTimeout(() => { this.user = data.text() }, 1000),
          this.user = this._subject.next(data),
                error => console.log(error) );

更新:

app.component.ts

import { Component, ViewEncapsulation, Output, EventEmitter } from '@angular/core';
import { ResourcesService } from './services/resources.service';
import { PrivilegeService } from './services/privilege.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
user: string;
constructor(
        private resourcesService: ResourcesService,
        private privilegeService: PrivilegeService
        ) { 

    if (Config.PROD_MODE)
        resourcesService.getUser().subscribe( data => {
            this.user = data.text(); 
            resourcesService.user = data.text();
        }, error => {console.log(error);

resource.service.ts:

  constructor(public http: Http){ 
  this.headers = new Headers({ 'Content-Type': 'application/json', 'Accept': 'application/json' });
  this.options = new RequestOptions({ headers: this.headers});}


/**
 * Get current user
 */
getUser(){
    let url = this.url + "user";  

    return this.http.get(url)
        //.catch( (error: any) => { console.log(error); return Observable.empty<Response>();} );
        .catch( (error: any) => Observable.throw(error || 'Server Error - could not get user') );
}

privilege.service.ts:

@Injectable()
export class PrivilegeService extends ResourcesService {
constructor(public http: Http){ 

  super(http);

  this.user = '';

resource-list.component:

public constructor(private resourcesService: ResourcesService,
                    private privilegeService: PrivilegeService, 
                    private router: Router, private route: ActivatedRoute) {

    if (Utils.isEmpty(this.resourcesService.user)){
        this.resourcesService.getUser().subscribe( data => {
            this.resourcesService.user = data.text();
            this.callGetResources();
        }, error => console.log(error) );
    }
}

我尝试将获取资源的调用移动到可观察块内,现在我得到了:

错误错误: InvalidPipeArgument: '' for pipe 'AsyncPipe' 在 invalidPipeArgumentError (common.es5.js:2610) 在 AsyncPipe.webpackJsonp.../../../common/@angular/common.es5.js.AsyncPipe._selectStrategy (common.es5.js:2755)

我意识到getResources()的调用是在设置resources.service的用户变量之前执行的:

  1. 在 app.component 中执行了对 getUser() 的调用,但数据仍未准备好。在调试时,我可以看到如下数据:

消息 : “输入意外结束” 堆 : "SyntaxError: 在新的 AppComponent (http://localhost:8080/DataFabResourceManager/dist/main.bundle.js:247:9) 处意外结束输入↵ ↵

  1. 然后对 getResources() 的调用是从资源列表页面(刷新时我站在的那个页面)执行的。但此时用户仍未定义

  2. 回到app.component,现在数据准备好了,资源服务的用户变量就坐好了(但是太晚了):

200 状态文本 : “好的” 类型 : 2 网址 : “http://localhost:8080/DataFabResourceManager/management/user” _身体 : “regressiontester_db” 原型

【问题讨论】:

  • 你可以从@angular/core 导入ChangeDetectorRef 并在你为this.user 赋值后调用detectChanges() 吗?那它行得通吗?如果是这样,问题可能在于您的异步调用结构方式;与 Angular 更改检测的生命周期存在冲突,因此当您分配一个值时,它不会被识别。
  • 什么时候调用你的代码?
  • @Lansana,detectChanges() 不起作用: resourcesService.getUser().subscribe( data => { this.user = data.text(); resourcesService.user = data.text(); detectRef .markForCheck(); detectRef.detectChanges(); }, error => {console.log(error); window.location.href = "../Login.html";} ); }, 1000);

标签: angular observable


【解决方案1】:

尝试执行以下操作:

在您的服务中创建将返回 observable 的函数:

getUser() {
    return http.get('here your rest api link to back-end');
}

然后从您的组件调用该方法,例如从 ngOnInit() 方法。 (您可以遵循 angular.io 的官方指南):

ngOnInit() {
    this.service.getUser().subscribe('here your subscribe logic'); 
}

还将 HttpClient 作为构造函数参数提供给您的服务。 然后也通过构造函数将您的服务提供给组件。

有用的链接:

https://angular.io/guide/dependency-injection

https://angular.io/guide/dependency-injection-pattern

http: https://angular.io/api/common/http/HttpClient

【讨论】:

  • 嗨@Pavel,这就是我实际拥有的!顺便说一句,我尝试了 Lansana 在他的评论中写的内容(使用 detectChanges() 方法),但没有任何不同。我需要找出为什么它在导航时使用路由器而不是在刷新浏览器时工作,主要是时间问题
  • @zbeedatm 嗨,您可以用组件和服务代码更新您的问题吗?
  • @zbeedatm 嗨,您是否尝试在组件代码中使用 ngOnInit() 方法?在那里打电话给你的服务?
  • 将调用移动到 ngOnInit() 也没有帮助:~
  • 请参阅我的“更新 2”部分。现在它是有道理的,我知道根本原因是什么,但我所做的解决方案是导致异常
猜你喜欢
  • 1970-01-01
  • 2014-07-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多