Angular 6 - заметная подписка не работает - PullRequest
0 голосов
/ 19 сентября 2018

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

Компонент получает подписанное значение только один раз, а служба получает данные каждые 2 секунды.Я проверил это, и сервис делает это правильно.

В моем случае это не так, если подсписок находится в 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)

  }
}

Ответы [ 2 ]

0 голосов
/ 19 сентября 2018

Вы можете сделать то, что вы хотите, используя Subject / Behavior: просто некоторые изменения в вашем сервисе

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
  }
0 голосов
/ 19 сентября 2018

Из вашего примера ясно, что служба получает его каждые 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...