【问题标题】:Rxjs subscribe method being ignoredRxjs 订阅方法被忽略
【发布时间】:2018-01-18 18:50:28
【问题描述】:

在将其标记为重复之前,请注意这些都不适合我:question 1 / question 2/ question 3

因此,在收到对以前的 question 的回复后,我开始使用 rxjs,遵循 guide 上提供的所有内容

但是,由于未触发 subscribe 方法,我很快又在过去几个小时内再次陷入困境。

我的服务编码如下:

import { Injectable } from '@angular/core';
import { Subject }    from 'rxjs/Subject';
import {FormDTO} from "../dto/formDTO.model";

@Injectable()
export class ApiDosageDialogFormCommunicationService {

    private formDTO = new Subject<FormDTO>();

    //Observable string streams
    formDTOpulling$ = this.formDTO.asObservable();

    //Service message commands
    formDTOpushing(formDTO: FormDTO) {
        this.formDTO.next(formDTO);
    }

将它从父母发送给孩子,例如:

this.apiDosageDialogFormCommunicationService.formDTOpushing(this.formDTO)

它工作正常,直到这里,服务接收 DTO,我可以读取它的值,但是当我尝试在模式服务中使用它时,订阅方法什么都不做,这是我的组件我正在尝试获取 DTO:

  import {Component, OnDestroy, OnInit} from "@angular/core";
import {JhiEventManager} from "ng-jhipster";
import {NgbActiveModal} from "@ng-bootstrap/ng-bootstrap";
import {Response} from "@angular/http";
import {ActivatedRoute} from "@angular/router";
import {Observable} from "rxjs/Rx";
import {FormService} from "./form.service";
import {FormDTO} from "../dto/formDTO.model";
import {ApiDosageDialogFirstStepPopupService} from "./apiDosage-dialog-first-step-popup.service";
import {ApiDosageDialogFormCommunicationService} from "./apiDosageDialogFormCommunication.service";
import {Subscription} from "rxjs/Subscription";

@Component({
    selector: 'jhi-apiDosage-dialog-first-step',
    templateUrl: './apiDosage-dialog-first-step.component.html'
})

export class ApiDosageDialogFirstStepComponent implements OnInit {

    formDTO: FormDTO;
    isSaving: boolean;

    constructor(
        public activeModal: NgbActiveModal,
        private formService: FormService,
        private apiDosageDialogFormCommunicationService: ApiDosageDialogFormCommunicationService,
        private eventManager: JhiEventManager
    ) {
    }

    ngOnInit() {
        this.isSaving = false;
    }

    clear() {
        this.activeModal.dismiss('cancel');
    }

    save() {
        this.isSaving = true;
        if (this.formDTO.id !== undefined) {
            this.subscribeToSaveResponse(
                this.formService.save(this.formDTO));
        } else {
            this.subscribeToSaveResponse(
                this.formService.save(this.formDTO));
        }
    }

    private subscribeToSaveResponse(result: Observable<FormDTO>) {
        result.subscribe((res: FormDTO) =>
            this.onSaveSuccess(res), (res: Response) => this.onSaveError());
    }

    private onSaveSuccess(result: FormDTO) {
        this.eventManager.broadcast({ name: 'journalListModification', content: 'OK'});
        this.isSaving = false;
        this.activeModal.dismiss(result);
    }

    private onSaveError() {
        this.isSaving = false;
    }
}

@Component({
    selector: 'jhi-apiDosage-first-step-popup',
    template: ''
})
export class ApiDosageDialogFirstStepPopupComponent implements OnInit, OnDestroy {

    routeSub: any;
    formDTO: any;
    subscription: Subscription;

    constructor(
        private route: ActivatedRoute,
        private apiDosagePopupService: ApiDosageDialogFirstStepPopupService,
        private apiDosageDialogFormCommunicationService: ApiDosageDialogFormCommunicationService
    ) {

    }

    ngOnInit() {
        this.subscription = this.apiDosageDialogFormCommunicationService.formDTOpulling$.subscribe(
            formDTO => {
                 console.log('In the component' +this.formDTO.sample.id),
                 this.formDTO = formDTO;
             },
             error => {
                 alert('Made it all the way here: '+this.formDTO);
             });
        this.routeSub = this.route.params.subscribe((params) => {
            this.apiDosagePopupService
                    .open(ApiDosageDialogFirstStepComponent as Component, this.formDTO);
        });
    }

    ngOnDestroy() {
        this.routeSub.unsubscribe();
    }
}

请注意,在上一课中,我尝试在 onInit 和构造函数中添加 subscribe 方法。

前面的类调用了modal的open方法,是modal的service的源码:

import { Injectable, Component } from '@angular/core';
import { Router } from '@angular/router';
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
import {FormService} from "./form.service";
import {FormDTO} from "../dto/formDTO.model";
import {Observable} from "rxjs/Observable";

@Injectable()
export class ApiDosageDialogFirstStepPopupService {
    private ngbModalRef: NgbModalRef;

    constructor(
        private modalService: NgbModal,
        private router: Router,
        private formService: FormService

    ) {
        this.ngbModalRef = null;
    }

    open(component: Component, formDTO?: Observable<any> | any): Promise<NgbModalRef> {
        return new Promise<NgbModalRef>((resolve, reject) => {
            const isOpen = this.ngbModalRef !== null;
            if (isOpen) {
                resolve(this.ngbModalRef);
            }
            if (formDTO) {
                  // this.formService.find(id).subscribe((journal) => {
                  //     this.ngbModalRef = this.journalModalRef(component, journal);
                  //     resolve(this.ngbModalRef);
                  // });
                setTimeout(() => {
                    this.ngbModalRef = this.apiDosageFirstStepModalRef(component, formDTO);
                         resolve(this.ngbModalRef);
                         console.log(formDTO);
                }, 0);
                } else {
                 //setTimeout used as a workaround for getting ExpressionChangedAfterItHasBeenCheckedError
                 setTimeout(() => {
                     this.ngbModalRef = this.apiDosageFirstStepModalRef(component, new Observable<any>());
                     resolve(this.ngbModalRef);
                 }, 0);
                alert('no form');
            }
        });
    }

    apiDosageFirstStepModalRef(component: Component, formDTO: Observable<any>): NgbModalRef {
        const modalRef = this.modalService.open(component, { size: 'lg', backdrop: 'static'});
        modalRef.componentInstance.formDTO = formDTO;
        modalRef.result.then((result) => {
            this.router.navigate([{ outlets: { popup: null }}], { replaceUrl: true, queryParamsHandling: 'merge' });
            this.ngbModalRef = null;
        }, (reason) => {
            this.router.navigate([{ outlets: { popup: null }}], { replaceUrl: true, queryParamsHandling: 'merge' });
            this.ngbModalRef = null;
        });
        return modalRef;
    }
}

【问题讨论】:

  • 在调用formDTOpushing 方法后,您的组件是否订阅了formDTOpulling$?如果是这样,他们将不会收到主题发射。他们只会在订阅后收到排放量。如果是这种情况,那么您可以使用 BehaviorSubject 或 ReplaySubject 之类的东西来接收订阅时发出的最后一个值。
  • 我相信是这样的,不会是这一行:this.subscription = this.apiDosageDialogFormCommunicationService.formDTOpulling$.subscribe( formDTO =&gt; { console.log('In the component' +this.formDTO.sample.id), this.formDTO = formDTO; }, error =&gt; { alert('Made it all the way here: '+this.formDTO); });?
  • 好吧,我太早看到你的评论了,所以你是在建议我一使用推送方法就给孩子打电话?
  • 我是说所谓的顺序很重要。所以可能发生的是 formDTOpushing 被调用(并且没有组件订阅该主题)。现在组件订阅。他们没有收到来自主题的值,因为formDTOpushing 发生在他们订阅之前。
  • 是否有类似的工作示例?我正在努力看看这是如何工作的,如果我在从父母推送之前尝试订阅主题,我会得到一个未定义的,不是吗?

标签: angular modal-dialog rxjs


【解决方案1】:

正在发生的事情是 formDTOpushing 在组件订阅之前被调用。这意味着组件将不会收到该值。订阅 Subject 的组件仅接收订阅后发出的值。 (他们最初订阅时没有收到值)

要让组件在订阅时接收先前发出的值,请改用 BehaviorSubject 或 ReplaySubject

【讨论】:

  • 天才!我将 private formDTO = new Subject&lt;FormDTO&gt;(); 更改为 private formDTO = new BehaviorSubject&lt;any&gt;(this.formDTO1); 并且效果很好
猜你喜欢
  • 1970-01-01
  • 2018-03-24
  • 2018-08-23
  • 2021-01-28
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多