Я новичок в Angular-7, RxJS-6 и Visual Studio Code, и у меня возникают трудности с отладкой Observable, который возвращается подписчику, в результате чего подписчик вызывает ошибку TypeError во время выполнения. Судя по исследованиям, я не одинок с такими сложными проблемами. Можете ли вы либо предложить, как я могу определить, что подписчик «наблюдает», либо вы можете найти ошибку в моем коде ниже?
Подробнее
Я пишу очень простое доказательство концепции, используя код Visual Studio и интерфейс командной строки Angular-7, чтобы получить текущую системную дату/время с сервера с помощью углового 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 и, возможно, ошибаюсь в использовании оператора карты. Что мне не хватает?
Кодекс
Ссылки на программное обеспечение этого фрагмента включают:
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-запросом/ответом, получая текущую дату/время с сервера.
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>
. Опять же, я упростил код (хотя он по-прежнему не работает) и преувеличил карту, чтобы лучше видеть, что я делаю.
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
) { }
}
this.http.get<SystemDateTimeResponse>(...)
, на самом деле было мусором. Похоже, то, что я считал правильным ответом get, было лишь подкомпонентом всего ответа http. Как выяснилось, весь код, который я вставил выше, был правильным. большое спасибо за вашу помощь еще раз. - person WillMcF   schedule 28.11.2018