简体   繁体   English

主题订阅未在组件中触发

[英]Subject subscribe is not triggering in a component

When I am trying to subscribe to Subject folder_id, it is not subscribing in the board component when I am passing the id in the files component.当我尝试订阅 Subject folder_id 时,当我在 files 组件中传递 id 时,它没有订阅 board 组件。

This boardId function is triggered when a button is pressed in the files component.当在文件组件中按下按钮时,会触发此 boardId function。 The activateId is the id taken from the snapshot of the url. activateId 是从 url 的快照中获取的 id。

  boardID(){
    this.apiService.folder_id.next(this.activateID.id);
    console.log(this.activateID.id);
  }

This is the ngOnInit in the boards component which has to subscribe the id that is emitted from the files component.这是 board 组件中的 ngOnInit,它必须订阅从 files 组件发出的 id。 But for some reason when I try to get the id in this component, it does not run this subscribe function.但是由于某种原因,当我尝试获取此组件中的 id 时,它不会运行此订阅 function。

  ngOnInit() {
    
    this.apiService.folder_id.subscribe(
      (_id : string) => {
       this.id = _id;
       console.log(this.id)
       
     }
   );

    this.page = 0;
    console.log('Screen width :', this.scrWidth, 'Screen height', this.scrHeight);

    // getting the 2D context of Canvas element
    this.canvasElement = this.canvas.nativeElement;
    this.ctx = this.canvasElement.getContext('2d');
    // setting the Width and Height to the canvas element
    this.renderer.setAttribute(this.canvasElement, 'width', this.scrWidth);
    this.renderer.setAttribute(this.canvasElement, 'height', this.scrHeight);

    // for background
    this.backgroundCanvas = this.background.nativeElement;
    this.renderer.setAttribute(this.backgroundCanvas, 'width', this.scrWidth);
    this.renderer.setAttribute(this.backgroundCanvas, 'height', this.scrHeight);

  }

Now this is the service.ts file:-现在这是 service.ts 文件:-

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Router } from '@angular/router';
import { environment } from 'src/environments/environment';
import { Subject } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class RestService {

  xAuthToken = null;
  boardId = null;
  gerBoardDetails = null;
  createFolderResponse = null;
  deleteFolderResponse = null;

  folder_id = new Subject<string>();
  
  constructor(private http: HttpClient, public router: Router) {}

Can someone please help me on this issue, I am stuck on this for many days now.有人可以帮我解决这个问题吗,我已经坚持了很多天了。 Thank you.谢谢你。

You should declare your subscribe method inside your constructor method, other way it will run just once (during the ngOnInit phase) and, if your subscribe does not catch any value during this execution, it will not catch any other else.您应该在构造函数方法中声明您的订阅方法,否则它将只运行一次(在ngOnInit阶段),并且如果您的订阅在此执行期间未捕获任何值,它将不会捕获任何其他值。 Declaring the the subscribe method on the constructor, you will be able to watch every event emitted.在构造函数上声明 subscribe 方法,您将能够看到发出的每个事件。

Then, if I understand correctly your problem, you want to emit the Subject from the service to the component.然后,如果我正确理解您的问题,您希望将主题从服务发送到组件。 For that, you will need to have a Subject type on your service AND an Observable type on your component, so you are able to listen the events emitted from the Subject.为此,您需要在您的服务上有一个Subject类型在您的组件上有一个Observable类型,这样您就可以监听从 Subject 发出的事件。 Also, will need to provide your subject as an Observable so you can watch it.此外,需要将您的主题作为Observable提供,以便您可以观看它。

Try to refactor your code like this:尝试像这样重构您的代码:

Service.ts服务.ts

folder_id = new Subject<string>();

emitFolderId(id: string) {
  this.folder_id.next(id);
}

getObservable() {
  return this.folder_id.asObservable();
}

Component.ts组件.ts

folder_id$: Observable<string>;

id: string;

constructor(private apiService: RestService) {
  folder_id$ = apiService.getObservable();
  folder_id$.subscribe(folder_id => {
      this.id = folder_id;
    }
  );
}

boardID() {
  this.apiService.emitFolderId(this.id);
}

Then, you should have your ID rendered correctly.然后,您应该正确呈现您的 ID。

If you are not sure if your component is rendered when your Subject comes up, try to replace Subject to BehaviourSubject .如果您不确定是否在 Subject 出现时渲染了您的组件,请尝试将Subject替换为BehaviourSubject

The BehaviourSubject will provide the last value to his watchers when is no other active, so you will be able to watch the every last value emmited from the BehaviourSubject, the only difference that you shold instantiate it with a starter value so it can emit the first value when it is instantiate. BehaviourSubject将在没有其他活动时将最后一个值提供给他的观察者,因此您将能够观察从 BehaviourSubject 发出的每个最后一个值,唯一的区别是您应该使用起始值实例化它,以便它可以发出第一个实例化时的值。

folder_id = new BehaviourSubject<string>(null);
    at RestService you must make 2 function methode
     1. setData(data: string ) {
       this.folder_id.next(data)
      }
    
     2. getData(res): Subscription {
     return this.folder_id.subscribe(res) 
     }

    and call getData function in your component 
    this.RestService.getData(res => { 
      console.log(res)
    })

You should first turn your Subject into an Observable as follow:你应该首先将你的 Subject 变成一个 Observable,如下所示:

folder_id$ = this.apiService.folder_id.asObservable();

And then subscribe to it in your onInit:然后在你的 onInit 中订阅它:

this.apiService.folder_id$
    .subscribe((_id : string) => {
        this.id = _id;
        console.log(this.id) 
    }

But, if you subscribe to this observable after a value was emitted, you will not see it because the value was emitted before you subscribed to it.但是,如果您在发出一个值之后订阅这个 observable,您将看不到它,因为该值是在您订阅它之前发出的。 In this case, you should use a ReplaySubject to emit previous values.在这种情况下,您应该使用ReplaySubject来发出先前的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM