0

我正在尝试以角度进行 get 调用,调用本身可以工作,因为我可以将日志放入订阅中并查看返回的数据我遇到的问题是我似乎无法将数据分配给我现有的数组(当前为空) 并且因为下面的代码是Event[]. 我尝试在数据数组上使用映射,它也是类型Event[]但没有运气,并且与推送相同,尽管我相信这是因为您无法推送数组。我确信有一些简单的东西我丢失或找不到。

这是我正在打的电话,并大声疾呼事件模型。

this.httpClient.get<Event[]>('http://127.0.0.1:5555/events-get').subscribe((data) => this.events = data); 


export class Event {
    constructor(public name: String, public date: Date, public time: Date) {}
}

我是 Angular 的新手,所以我可能做错了任何帮助都非常感谢。

编辑

我做了更多的研究,但仍然没有乐趣,也许这与订阅它有关。我从这里尝试了一些阵列克隆解决方案

编辑 2

进一步看,我看到 subscribe 的内容是一个函数,我在范围中缺少什么我this.events需要以某种方式传递,它是在类级别设置的。

编辑 3

import { Event } from '../shared/event.model';
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Subject } from 'rxjs';
import { map } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http'

@Injectable()
export class AdminService {
    eventsChanged = new Subject<Event[]>();

    private events: Event[] = [];

    constructor(private http: Http, private httpClient: HttpClient) {}

    getEvents() {
        this.httpClient.get<Event[]>('http://127.0.0.1:5555/events-get')
        .pipe(
            map(
                (data: Event[]) => data.map(event => {
                // may need to coerce string to Date types
                    return new Event(event.name, event.date, event.time)
                })
            )
        )
        .subscribe((events: Event[]) => this.events = events);

        console.log(this.events);
        return this.events;
}

然后我在我的组件中使用这个调用,这与使用本地数组Event[].

 this.events = this.adminService.getEvents();
4

3 回答 3

4

基本问题是您试图在解析/发出和执行/分配之前Event[]从您的方法中返回数据,这就是为什么它总是返回一个空数组。这就是RxJS 的异步特性。AdminService.getEvents()httpClient.get<Event[]>()subscribe()HttpClient

@Injectable()
export class AdminService {
// ...

getEvents() {
    // this happens after console.log() and return this.events
    .subscribe((events: Event[]) => this.events = events);

    // this executes before get()/subscribe() resolves, so empty [] is returned
    console.log(this.events);
    return this.events;
}

而是返回 theget<Event[]>().pipe()@Component调用和使用:

import { Event } from '../shared/event.model';
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Subject, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http'

@Injectable()
export class AdminService {
  eventsChanged = new Subject<Event[]>();

  constructor(private http: Http, private httpClient: HttpClient) {}

  getEvents(): Observable<Event[]> {
    return this.httpClient.get<Event[]>('http://127.0.0.1:5555/events-get')
      .pipe(
        map(
          (data: Event[]) => data.map(event => {
            // may need to coerce string to Date types
            return new Event(event.name, event.date, event.time)
           })
        )
      );
  }

零件:

@Component({ /* ... */ })
export class EventsComponent implements OnInit {
  events$: Observable<Event[]>;

  constructor(private adminService: AdminService) {}

  ngOnInit() {
    this.events$ = this.adminService.getEvents();
  }
}

带有异步管道的模板:

<ul>
  <li *ngFor="let event of events$ | async">{{event.name}}</li>
</ul>

或者:

@Component({})
export class EventsComponent implements OnInit {
  events: Event[] = [];

  constructor(private adminService: AdminService) {}

  ngOnInit() {
    this.adminService.getEvents()
      .subscribe(events => this.events = events);
  }
}

模板:

<ul>
  <li *ngFor="let event of events">{{event.name}}</li>
</ul>

附带说明一下,HttpClient类型不会自动Event从 typed 创建类的实例get(),它是具有 set 类型的对象。您可以结合使用 RxJSmap运算符Array.prototype.mapEventEventget<Event[]>. 还要小心命名它Event,因为它可能与现有符号Event冲突。

希望这会有所帮助!

于 2018-09-01T16:20:50.413 回答
1

您的代码存在多个问题。

根据您的代码,您无法理解 RxJS Observable。当您终于准备好收听时,您调用订阅。所以你的getEvents()方法不应该订阅,而是返回 observable。IE

getEvents(): Observable<Event[]> {
  return this.httpClient
    .get<Event[]>("http://127.0.0.1:5555/events-get")
    .pipe(
      map(data =>
        data.map(event => new Event(event.name, event.date, event.time))
      )
    );
}

既然你用过

<ul>
  <li *ngFor="let event of events$ | async">{{event.name}}</li>
</ul>

async管道subscribe在 html 中为您执行此操作。只需公开events$您已经在ngOnInit().

我不会将我的接口定义为Event因为Event它已经是RxJS的一部分。

此外,由于你在订阅之外调用你的 console.log,它总是为 null,除非你像这样tapRxJS添加一个。

import { Event } from "../shared/event.model";
import { Injectable } from "@angular/core";
import { Http, Response } from "@angular/http";
import { Subject } from "rxjs";
import { map, tap } from "rxjs/operators";
import { HttpClient } from "@angular/common/http";

@Injectable()
export class AdminService {
  constructor(private http: Http, private httpClient: HttpClient) {}

  getEvents(): Observable<Event[]> {
    return this.httpClient
      .get<Event[]>("http://127.0.0.1:5555/events-get")
      .pipe(
        map(data =>
          data.map(event => new Event(event.name, event.date, event.time))
        ),
        tap(console.log)
      );
  }
}

另外,你为什么同时调用Httpand HttpClient。使用客户端或http。

快乐编码

于 2018-09-01T21:10:20.133 回答
0

通过查看您的第三次编辑,我认为这些map/pipe问题是一个红鲱鱼,核心问题是在http同步行为的公共方法签名内实现异步调用,即getEvents().

例如,我希望这个代码片段的行为类似,因为该方法能够立即返回this.events,其值仍然是一个空数组,然后继续执行异步内部的指定行为setTimeout

private events: Event[] = [];
private event1: Event = new Event("event1", "date", "time");
private event2: Event = new Event("event2", "date", "time");
public getEvents(): Event[] {
   setTimeout(() => {
     this.events = [..., event1, event2];
   }, 5000);

   return this.events;
}

对于您的代码示例,您是否能够通过与此类似的代码实现获得所需的结果。StackBlitz上可用的完整功能实现:

export class AdminService {
...
   public getEvents(): Observable<Event[]> {
   // Returns an observable
   return this.httpClient.get<Event[]>(url);
  }
}

export class EventComponent {

constructor(private adminService: AdminService) {}
    public events: Event[] = [];

    ngOnInit() {
        // Subscribe to the observable and when the asynchronous method
        // completes, assign the results to the component property.
        this.adminService.getEvents().subscribe(res => this.events = res);
    }
}
于 2018-09-01T19:02:14.553 回答