如何调试返回给Angular Observable订户的对象类型?

时间:2018-11-26 09:36:57

标签: angular typescript angular7 angular-httpclient rxjs6

我是 Angular-7 RxJS-6 Visual Studio Code 的新手,调试调试Observable对象时遇到困难返回给订阅服务器的结果是订阅服务器引发了运行时“ TypeError”。从研究看来,我并不孤单地遇到像这样的棘手问题。您可以建议我如何确定订户正在“观察”什么,还是可以在下面的代码中发现错误?

详细信息

我正在使用Visual Studio Code和Angular-7 CLI编写一个非常简单的概念证明,以使用angular的httpclient从服务器检索当前系统日期/时间并显示它。

请参阅下面的方法 instrument.service.ts :: getSystemTimeDate()。 HTTP层很好,因为可以获得JSON响应...

{
  "SystemDateTime": "2018-11-26T08:54:06.894Z"
}

map运算符内,此响应首先转换为SystemDateTimeResponse类型的对象,然后转换为Date,并且该方法应将Observable<Date>返回给任何订阅者。我遇到的麻烦是该组件对Observable<Date>的订阅。在运行时,方法onTimeDateBtnClick()中的该订户引发错误:

ERROR
TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
message: "You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable."
stack: "TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
    at subscribeTo (http://localhost:4200/vendor.js:75870:15)
    at subscribeToResult (http://localhost:4200/vendor.js:76027:76)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._innerSub (http://localhost:4200/vendor.js:70784:90)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._tryNext (http://localhost:4200/vendor.js:70778:14)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/mergeMap.js.MergeMapSubscriber._next (http://localhost:4200/vendor.js:70761:18)
    at MergeMapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (http://localhost:4200/vendor.js:65218:18)
    at TapSubscriber.push../node_modules/rxjs/_esm5/internal/operators/tap.js.TapSubscriber._next (http://localhost:4200/vendor.js:73228:26)
    at TapSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (http://localhost:4200/vendor.js:65218:18)
    at TakeSubscriber.push../node_modules/rxjs/_esm5/internal/operators/take.js.TakeSubscriber._next (http://localhost:4200/vendor.js:72950:30)
    at TakeSubscriber.push../node_modules/rxjs/_esm5/internal/Subscriber.js.Subscriber.next (http://localhost:4200/vendor.js:65218:18)"
__proto__: Error {constructor: , name: "TypeError", message: "", …}
constructor: function TypeError() { … }
message: ""
name: "TypeError"
toString: function toString() { … }
__proto__: Object {constructor: , name: "Error", message: "", …}

我认为我没有正确返回 Observable ,并且可能会加重我对map运算符的使用。我想念什么?


代码

此代码段的软件参考包括:

timedate.component.html :包含的简单模板

<p>
  Last time I checked, it was : {{today | date:'medium'}}
</p>
<button mat-button (click)="onTimedateBtnClick()">Update</button>

timedate.component.ts :包含today的显示属性定义和使用数据服务来管理HTTP请求/响应的事件处理程序onTimedateBtnClick()。服务器上的当前日期/时间。

import { Component, OnInit } from '@angular/core';
import { InstrumentService } from '../instrument.service';
import { Observable } from 'rxjs';

@Component({
  selector: 'app-timedate',
  templateUrl: './timedate.component.html',
  styleUrls: ['./timedate.component.css']
})
export class TimedateComponent implements OnInit {

  /** Display property */
  today: Date;

  /**
   * Constructor
   * @param - data service
   */
  constructor(private dataService: InstrumentService) {
  }

  ngOnInit() {
    this.today = new Date();  /// initialise with client's date/time
  }

  /**
   *  User event handler requesting system time/date from the server
   */
  onTimedateBtnClick() {
    const http$: Observable<Date> = this.dataService.getSystemTimeDate();

    http$.subscribe(
      res => this.today = res,
    );
  }
}

instrument.service.ts :包含getSystemTimeDate()方法,该方法返回Observable<Date>。再次,我简化了代码(尽管仍然失败),并夸大了 map 以便更好地了解我在做什么。

import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import { map } from 'rxjs/operators';

// App imports
import { SystemDateTimeResponse, SystemDateTimeUrl } from './instrument.service.httpdtos';


@Injectable({
  providedIn: 'root'
 })
export class InstrumentService {

  constructor(private http: HttpClient) { }

  /**
   * Return the server date and time
   */
  public getSystemTimeDate(): Observable<Date> {
    // Convert the server response object into an observable date
    const responseObject: Observable<Date> =
    this.http.get<SystemDateTimeResponse>(SystemDateTimeUrl.Url).
      pipe(
        map(jsonResponse => {
          const newDto = new SystemDateTimeResponse(jsonResponse.SystemDateTime);
          const d = new Date(newDto.SystemDateTime);
          return d;
        }),
      );

    return responseObject;
  }
}

instrument.service.httpdtos.ts :包含数据传输对象定义。

/** URL - Instrument system date/time */
export class SystemDateTimeUrl {
  public static readonly HttpVerb = 'GET';
  public static readonly Url = 'api/instrument/systemdatetime';
  public static readonly Summary = 'Query the instrument current date/time';
}

/** Response DTO */
export class SystemDateTimeResponse {
  constructor(
    public SystemDateTime: string     // In UTC format
  ) { }
}

1 个答案:

答案 0 :(得分:0)

您有两个选择。如果您使用Chrome来开发此应用程序,则可以使用开发人员工具,在webpack中找到源代码,并且可以在服务中添加多个断点以进行调试。棘手的部分是找到来源。从那里应该向前迈进。 enter image description here

第二个选项,如果您使用Intellij IDEA / WebStorm,则可以在编辑器中调试该应用程序。为此,您必须在Chrome / Firefox中安装JetBrains IDE Support扩展名,然后必须配置编辑器以添加新的Configuration:Editor Configuration-> Javascript Debugger。您必须指定正确的端口(如果您的应用程序在其他端口上运行)enter image description here 一旦启动了应用程序和调试配置,就可以在代码中添加一个新的断点(订阅/映射函数的回调),您应该能够检查所拥有的变量。

如果还有其他问题,请随时提出。