Как я могу отлаживать тип объекта, возвращаемый подписчику наблюдаемого Angular?

Я новичок в 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
  ) { }
}

person WillMcF    schedule 26.11.2018    source источник
comment
http$.subscribe( res =› { //Выполнить отладку здесь this.today = res; } );   -  person Vijay Sankhat    schedule 26.11.2018
comment
Опубликуйте точную и полную ошибку, которую вы получаете. сообщите нам, к какой строке (строкам) он относится.   -  person JB Nizet    schedule 26.11.2018
comment
@Vijay, большое спасибо, но, к сожалению, ошибка возникает в библиотеках Angular до того, как вызывается анонимная функция подписчика.   -  person WillMcF    schedule 26.11.2018
comment
@JB, большое спасибо - ты прав. Я добавил в сообщение некоторые пояснения, показывающие, что ошибка возникает из-за библиотек Angular. Я полагаю, что мог бы углубиться и установить там точки останова.   -  person WillMcF    schedule 26.11.2018
comment
@ billmcf123 Вы проверили эту ошибку в отладчике Chrome? или вы определили эту ошибку? Пожалуйста, вставьте сюда журнал ошибок.   -  person Vijay Sankhat    schedule 27.11.2018
comment
@Vijay В конце концов я смог научиться отлаживать проблему с помощью Chrome и обнаружил, что глубоко погрузился в наблюдаемую библиотеку rxjs. Я смог увидеть, что наблюдаемое, которое, как мне казалось, возвращалось из this.http.get<SystemDateTimeResponse>(...), на самом деле было мусором. Похоже, то, что я считал правильным ответом get, было лишь подкомпонентом всего ответа http. Как выяснилось, весь код, который я вставил выше, был правильным. большое спасибо за вашу помощь еще раз.   -  person WillMcF    schedule 28.11.2018
comment
@ billmcf123 Тогда, пожалуйста, проголосуйте за мой комментарий.   -  person Vijay Sankhat    schedule 29.11.2018
comment
@ Виджей, я бы хотел. Моя репутация еще слишком мала.   -  person WillMcF    schedule 30.11.2018


Ответы (1)


У вас есть два варианта. Если вы используете Chrome для разработки этого приложения, вы можете зайти в инструменты разработчика, найти свой исходный код в веб-пакете, а в сервисе вы можете добавить несколько точек останова для целей отладки. Сложность заключается в том, чтобы найти исходники. Оттуда он должен быть прямо вперед. введите здесь описание изображения

Второй вариант, если вы используете Intellij IDEA/WebStorm, вы можете отлаживать приложение в своем редакторе. Для этого необходимо установить расширение JetBrains IDE Support в Chrome / Firefox, и после этого вы должны настроить свой редактор, чтобы добавить новую конфигурацию: Конфигурация редактора -> Отладчик Javascript. Вы должны указать правильный порт (если ваше приложение работает на другом порту) введите здесь описание изображения После запуска приложения и конфигурации отладки добавьте в код новую точку останова (обратный вызов в вашей функции подписки/карты), и вы сможете проверить, какие переменные у вас есть.

Если у вас есть другие вопросы, не стесняйтесь спрашивать.

person Adrian Claudiu Dima    schedule 26.11.2018
comment
Большое спасибо. Использование отладчика Chrome помогло мне разобраться в проблеме (описанной выше). - person WillMcF; 28.11.2018