可观察性如何运作?

How observable works?

我正在向 https://www.youtube.com/watch?v=3dHNOWTI7H8 学习 我的服务是

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http'
import { Observable } from 'rxjs';
import { Schedule } from '../../../Schedule';

@Injectable({
  providedIn: 'root'
})
export class ScheduleService {
  private apiUrl = 'http://localhost:5000/schedules'

  constructor(private http:HttpClient) { }

  getSchedules(): Observable<Schedule[]> {
    console.log('get');
    return this.http.get<Schedule[]>(this.apiUrl);
  }
}

以及服务中get函数的调用

import { Component, OnInit } from '@angular/core';
import { Schedule } from '../../../../Schedule';
import { ScheduleService } from 'src/app/services/schedule.service';

@Component({
  selector: 'app-scheduler',
  templateUrl: './scheduler.component.html',
  styleUrls: ['./scheduler.component.css']
})
export class SchedulerComponent implements OnInit {
  schedules: Schedule[] = [];
  times: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

  constructor(private scheduleService:ScheduleService) {     
  }

  ngOnInit(): void {
    this.scheduleService.getSchedules().subscribe((s) => {
      console.log(s[0].weekDay);
      this.schedules = s;
    });
  }
}

当我在组件的 html 部分使用 schedule

<table class="table table-bordered">
    <thead class="thead-light">
        <tr>
            <th>Time</th>
            <th>Sun</th>
            <th>Mun</th>
            <th>Tue</th>
            <th>Wed</th>
            <th>Thu</th>
            <th>Fri</th>
            <th>Sat</th>
        </tr>
    </thead>
    <tbody>
        <ng-container *ngFor="let s of times; index as i">
            <tr>
                <td>Slot</td>
                <td *ngIf="schedules[0].times[i] !== 0" [attr.rowspan]="schedules[0].times[i]" class="bg-light text-dark">
                    d
                </td>
                <td *ngIf="schedules[1].times[i] !== 0" [attr.rowspan]="schedules[1].times[i]" class="bg-light text-dark">
                    d
                </td>
                <td *ngIf="schedules[2].times[i] !== 0" [attr.rowspan]="schedules[2].times[i]" class="bg-light text-dark">
                    d
                </td>
                <td *ngIf="schedules[3].times[i] !== 0" [attr.rowspan]="schedules[3].times[i]" class="bg-light text-dark">
                    d
                </td>
                <td *ngIf="schedules[4].times[i] !== 0" [attr.rowspan]="schedules[4].times[i]" class="bg-light text-dark">
                    d
                </td>
                <td *ngIf="schedules[5].times[i] !== 0" [attr.rowspan]="schedules[5].times[i]" class="bg-light text-dark">
                    d
                </td>
                <td *ngIf="schedules[6].times[i] !== 0" [attr.rowspan]="schedules[6].times[i]" class="bg-light text-dark">
                    d
                </td>
            </tr>
        </ng-container>

    </tbody>
</table>

我得到 Cannot read properties of undefined (reading 'times')。我知道我收到此错误的原因,并且在本网站的其他地方有 。但是

为什么它在上面的视频中有效而对我无效?我的代码和视频有什么区别?

对于你初始化的初学者

schedules: Schedule[] = []

此时数组中没有元素。您可以通过遍历结果来防止调用数组中不存在的位置:

<ng-container *ngFor="let s of times; index as i">
    <tr>
        <td>Slot</td>
        <ng-container *ngFor="let schedule of schedules">
            <td *ngIf="schedule.times[i] !== 0" [attr.rowspan]="schedule.times[i]" class="bg-light text-dark">
                    d
            </td>
        </ng-container>
    </tr>
</ng-container>

你确定schedule对象上有times数组吗? 我注意到你的组件中有一个时间数组作为成员, 你已经在循环播放了。

如果这是有意为之,您可能需要考虑更好的命名方式。 这只会让人在阅读代码时感到困惑。

此外,无需订阅可观察对象。 您可以只分配可观察对象并在模板中使用异步管道。

  • 这允许使用 OnPush 更改检测策略。
  • 您不必担心取消订阅您的 observable。

示例:

schedules$ = this.scheduleService.getSchedules()
<ng-container *ngFor="let schedule of schedules$ | async">