【问题标题】:Angular 6 - observable subscription doesn't workAngular 6 - 可观察订阅不起作用
【发布时间】:2018-09-20 14:17:05
【问题描述】:

我有以下情况。服务通常是从服务器获取数据,这些数据需要在其他组件中更新。

组件仅获取一次订阅值,但服务每 2 秒获取一次数据。我测试了它,服务做得对。

如果 subscirption 在 ngOnInit 或构造函数中,则在我的情况下不是

组件:

import {Component, OnInit} from '@angular/core';
import {TaskService} from "../../services/task.service";
import {Task} from "../../models/task";

@Component({
  selector: 'app-tasks',
  templateUrl: './tasks.component.html',
  styleUrls: ['./tasks.component.css']
})
export class TasksComponent implements OnInit {
  tasks: Task[];

  constructor(private taskService: TaskService) {
    this.taskService.getTasks().subscribe(tasks => {  // this is triggered only once, why ?
      this.tasks = tasks;
      console.log(tasks);
    });
  }

  ngOnInit() {

  }

  updateTask(task: Task) {
    try {
      task.completed = !task.completed;
      this.taskService.updateTask(task).subscribe();
    }
    catch (e) {
      task.completed = !task.completed;
    }
  }

}

服务:

import {Injectable} from '@angular/core';
import {HttpClient, HttpHeaders} from "@angular/common/http";
import {Observable, of, timer} from "rxjs";
import {Task} from "../models/task";


const httpOptions = {
  headers: new HttpHeaders({'Content-Type': 'application/json'})
};


@Injectable({
  providedIn: 'root'
})


export class TaskService {

  tasks: Task[];
  tasksURL = 'http://localhost:8080/api/tasks/';

  constructor(private http: HttpClient) {

    timer(1000, 2000).subscribe(() => {
      this.http.get<Task[]>(this.tasksURL).subscribe(value => this.tasks = value)
    }); // fetches and update the array every 2 seconds
  }

  getTasks(): Observable<Task[]> {
    return of(this.tasks); //returns observable which is than used by the component
  }

  updateTask(task: Task): Observable<Task> {
    const url = `${this.tasksURL}`;

    return this.http.post<Task>(url, task, httpOptions)

  }
}

【问题讨论】:

标签: angular typescript angular6


【解决方案1】:

您可以通过使用 Subject/Behaviour 来做您想做的事:只需对您的服务进行一些更改

import { BehaviorSubject } from 'rxjs/BehaviorSubject';

export class TaskService {

  tasks: new BehaviorSubject<Task[]>([]);
  tasksURL = 'http://localhost:8080/api/tasks/';

  constructor(private http: HttpClient) {

     timer(1000, 2000).subscribe(() => {
       this.http.get<Task[]>(this.tasksURL).subscribe( (value) => { 
         this.tasks.next(value);
       })
     }); // fetches and update the array every 2 seconds
  }

  getTasks(): Observable<Task[]> {
        return tasks.asObservable(); //returns observable which is then used by the component
  }

【讨论】:

    【解决方案2】:

    通过您的示例,很明显,由于

    ,该服务每 2 秒获取一次
    timer(1000, 2000).subscribe(() => {
    

    在组件中,您的订阅只是没有间隔。由于 getTask 稍后不会发出事件,因此不会更新任何内容。

    要么在组件中使用计时器(不优雅),要么手动发出.next

    服务中:

    public myObserver$: Subject<any>;
    [...]
    constructor(private http: HttpClient) {
    
      timer(1000, 2000).subscribe(() => {
        this.http.get<Task[]>(this.tasksURL).subscribe(value => {
          this.tasks = value;
          myObserver$.next(this.tasks);
        )}
      }); // fetches and update the array every 2 seconds
    }
    

    然后您可以在服务中订阅myObserver$ 而不是getTasks() 方法。您不需要组件中的计时器。

    您还应该将组件中的订阅存储到一个变量中:

    private subscriptionRef: Subscription;
    
    constructor(private taskService: TaskService) {
      this.subscription = this.taskService.getTasks().subscribe(tasks => {  // this is triggered only once, why ?
      this.tasks = tasks;
      });
    }
    

    以便您可以在 ngOnDestroy 方法中取消订阅。

    ngOnDestroy(): void {
      this.subscription.unsubscribe();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-15
      • 2018-11-22
      • 1970-01-01
      • 2023-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-12
      相关资源
      最近更新 更多