Angular observable:为什么参数未定义

时间:2018-01-10 15:20:24

标签: angular typescript observable

我对Observable参数有疑问,在我的情况下,我有一个具有函数consult()的consultService和参数响应。在使用参数响应之前调用sendConsultRequest()函数。 sendConsultRequest工作正常,因为我可以在页面中看到结果,但是当我想通过使用参数响应导出内容时,我遇到了问题:

  

错误类型错误:无法读取属性' dataList'未定义的

在我的操作中,响应参数已在导出操作之前初始化,因为consultPage运行良好。 这是服务代码,你能告诉我它为什么不起作用吗?

@Injectable()
export class ConsultService {
  private url = 'api/consultApplication';
  response: Application;

sendConsultRequest(id: string) {
  console.log('sendConsultRequest');
  this.http.get<Application[]>(this.url)
    .subscribe(response => {
      response.map(res => {
        this.response = res;
        this.updateApplication(res);
      }),
        pipe(catchError(this.handleError('sendConsultRequest', [])));
    });
}

这是导出页面ts:

ngOnInit() {
  console.log('ExportComponent init');
  console.log(this.consultService.response);
  this.application = this.consultService.response;

  this.appID= this.consultService.response.dataList.find(pair => 'PROCEDURE' === pair.field)
      ? this.consultService.response.dataList.find(pair => 'PROCEDURE' === pair.field).value : null;
}

谢谢。

2 个答案:

答案 0 :(得分:2)

这不是它的工作方式。

以下是它的工作原理。

@Injectable()
export class ConsultService {
  private url = 'api/consultApplication';
  response: Application;

sendConsultRequest() {
  console.log('sendConsultRequest');
  return this.http.get<Application[]>(this.url)
}

在您的组件中

ngOnInit() {
  console.log('ExportComponent init');
  console.log(this.consultService.response);

  this.consultService.sendConsultRequest().subscribe(
    response => {
      response.map(res => {
        this.consultService.updateApplication(res);
        this.appID = response.dataList.find(pair => 'PROCEDURE' === pair.field); 
      });
    }, error => this.consultService.handleError('sendConsultRequest', [])
  );
}

你这样做的方式,你从不打电话给你的服务(或者你没有发布代码)。并且由于您的服务进行异步调用,并且您希望等待它,您应该让组件等待它,而不是您的服务。

您采用这种方式,您的组件不会等待您的服务结束通话。它只是取一个蓝色的值,这个值可能等于null或undefined。

答案 1 :(得分:2)

每当出现Cannot read property 'foo' of undefined错误时,这意味着您尝试从中读取数据的对象从未分配过值。

在JavaScript中,如果您没有设置某些内容,它将始终默认为undefined

let foo; // foo is undefined

此外,如果您期望函数中的参数但该参数从未赋值,那么它也将是未定义的。

function foo(arg) {
   console.log(foo);
}

foo(); // the console logs 'undefined'

因此,当您遇到这类错误时,这是​​一个很好的经验法则,这意味着变量从未在代码中分配过值,您应该查看您正在分配的思考的位置它是一个值,并重新读取代码,以确保它实际上是你想要它的工作。

这一行:

this.appID= this.consultService.response.dataList.find(pair => 'PROCEDURE' === pair.field)
  ? this.consultService.response.dataList.find(pair => 'PROCEDURE' === pair.field).value : null;

在这种情况下不起作用,因为this.consultService.response未定义。您只能在为this.consultService.response分配值后调用该逻辑。

未定义的原因是您进行异步HTTP调用,然后尝试立即访问该值。但HTTP调用尚未返回,因此您的值将不确定。

如果要从异步HTTP调用接收值,则应从服务返回observable,然后在组件中订阅它。

服务:

sendConsultRequest(id: string): Observable<any> {
  return this.http.get<Application[]>(this.url).pipe(
    tap(response => {
      return response.map(res => {
        this.response = res;
        this.updateApplication(res);
      })
    ),
    catchError(this.handleError('sendConsultRequest', []))
  );
}

现在在您的组件中:

ngOnInit() {
    this.consuleService
        .sendConsuleRequestId(id)
        .subscribe(response => {
            this.appID = response.dataList.find(pair => 'PROCEDURE' === pair.field) ? response.dataList.find(pair => 'PROCEDURE' === pair.field).value : null;
        });
}

更新(显示ReplaySubject示例) - 未经测试:

服务:

consultStream: ReplaySubject = new ReplaySubject();
consult$: Observable<Consult> = this.consultStream.asObservable();

constructor() {
     this.sendConsultRequest(1);
}

sendConsultRequest(id: string): Observable<any> {
  return this.http.get<Application[]>(this.url)
      .subscribe((consult: Consult) => this.consultStream.next(consult));
}

组件:

ngOnInit() {
    this.consult$
        .subscribe((consult: Consult) => {
            // ...
        });
}