如何调试返回给 Angular 可观察对象订阅者的对象类型?
How can I debug the object type returned to the subscriber of an Angular observable?
我是 Angular-7、RxJS-6 和 [= 的新手87=] 代码 并且我在调试一个被 return 发送给订阅者的 Observable 时遇到了困难,结果我有一个运行时 "TypeError" 被订阅者引发。从研究来看,似乎并不是我一个人遇到这样棘手的问题。你能建议我如何确定订阅者是什么 "observing" 或者你能发现我下面代码中的错误吗?
详细
我正在使用 Visual Studio 代码和 Angular-7 CLI 编写一个非常简单的概念证明,以使用 angular 从服务器检索当前系统 date/time ]的httpclient
并显示出来。
参考下面的方法instrument.service.ts::getSystemTimeDate()。 HTTP 层很好,因为获得了 JSON 响应 ...
{
"SystemDateTime": "2018-11-26T08:54:06.894Z"
}
在 map
运算符中,此响应首先转换为 SystemDateTimeResponse
类型的对象,然后转换为 Date
并且该方法应该 return 一个 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: "", …}
我认为我没有正确地 returning 一个 Observable 并且可能搞砸了我对地图运算符的使用。我错过了什么?
代码
此代码段的软件参考包括:
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
的显示属性定义和使用数据服务的事件处理程序onTimedateBtnClick()
管理 HTTP request/response,从服务器检索当前 date/time。
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()
方法,其中 return 是 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
) { }
}
你有两个选择。如果你使用 Chrome 来开发这个应用程序,你可以进入开发者工具,在 webpack 中找到你的源代码,并且在服务中你可以添加多个断点用于调试目的。棘手的部分是找到来源。从那里它应该是海峡前进。
第二个选项,如果你使用Intellij IDEA / WebStorm,你可以在你的编辑器中调试应用程序。为此,您必须安装 JetBrains IDE Support extension in Chrome / Firefox and after that you must configure your editor to add a new Configuration : Editor Configuration -> Javascript Debugger. You must specify the correct port (if your app runs on a different port)
启动应用程序和调试配置后,在您的代码中添加一个新断点(订阅/地图函数的回调),您应该能够检查您拥有的变量。
如果您有任何其他问题,请随时提出。
我是 Angular-7、RxJS-6 和 [= 的新手87=] 代码 并且我在调试一个被 return 发送给订阅者的 Observable 时遇到了困难,结果我有一个运行时 "TypeError" 被订阅者引发。从研究来看,似乎并不是我一个人遇到这样棘手的问题。你能建议我如何确定订阅者是什么 "observing" 或者你能发现我下面代码中的错误吗?
详细
我正在使用 Visual Studio 代码和 Angular-7 CLI 编写一个非常简单的概念证明,以使用 angular 从服务器检索当前系统 date/time ]的httpclient
并显示出来。
参考下面的方法instrument.service.ts::getSystemTimeDate()。 HTTP 层很好,因为获得了 JSON 响应 ...
{
"SystemDateTime": "2018-11-26T08:54:06.894Z"
}
在 map
运算符中,此响应首先转换为 SystemDateTimeResponse
类型的对象,然后转换为 Date
并且该方法应该 return 一个 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: "", …}
我认为我没有正确地 returning 一个 Observable 并且可能搞砸了我对地图运算符的使用。我错过了什么?
代码
此代码段的软件参考包括:
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
的显示属性定义和使用数据服务的事件处理程序onTimedateBtnClick()
管理 HTTP request/response,从服务器检索当前 date/time。
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()
方法,其中 return 是 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
) { }
}
你有两个选择。如果你使用 Chrome 来开发这个应用程序,你可以进入开发者工具,在 webpack 中找到你的源代码,并且在服务中你可以添加多个断点用于调试目的。棘手的部分是找到来源。从那里它应该是海峡前进。
第二个选项,如果你使用Intellij IDEA / WebStorm,你可以在你的编辑器中调试应用程序。为此,您必须安装 JetBrains IDE Support extension in Chrome / Firefox and after that you must configure your editor to add a new Configuration : Editor Configuration -> Javascript Debugger. You must specify the correct port (if your app runs on a different port)
如果您有任何其他问题,请随时提出。