【问题标题】:How to wait for methods called in a subscription?如何等待订阅中调用的方法?
【发布时间】:2020-12-24 16:08:38
【问题描述】:

我有以下代码:

clickEventsubscription: Subscription;
  constructor(
    private activatedRoute: ActivatedRoute,
    private newsService: NewsService,
    private app: AppComponent,
    private EventlistenerService: EventlistenerService,
    public modalController: ModalController
  ) {
    this.clickEventsubscription = this.EventlistenerService.getClickEvent().subscribe(() => {
      this.update();
    });
  }
  
  update() {
    this.resetParameters();
    this.ngOnInit();
  }

我想等到 resetParameters();完成后再调用 ngOnInit();或其他一些类导致我想先重置参数,以便加载但不会重置参数...

这是我的完整代码:

import { Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Subscription } from 'rxjs';
import { IonInfiniteScroll } from '@ionic/angular';
import { ModalController } from '@ionic/angular';
import { ArticlePage } from '../article/article.page';
import { NewsService } from '../services/news.service';
import { AppComponent } from '../app.component';
import { EventlistenerService } from '../services/eventlistener.service';

@Component({
  selector: 'app-folder',
  templateUrl: './folder.page.html',
  styleUrls: ['./folder.page.scss'],
})
export class FolderPage implements OnInit {
  @ViewChild(IonInfiniteScroll, { static: true }) infiniteScroll: IonInfiniteScroll;

  clickEventsubscription: Subscription;

  public folder: string;
  data: any;
  page = 1;
  private country: string = '';
  private category: string = '';
  public search: string = '';
  public showInfiniteScroll: boolean = true;
  private language: string;
  private from: string;
  private to: string;
  private sortBy: string;

  constructor(
    private activatedRoute: ActivatedRoute,
    private newsService: NewsService,
    private app: AppComponent,
    private EventlistenerService: EventlistenerService,
    public modalController: ModalController
  ) {
    this.clickEventsubscription = this.EventlistenerService.getClickEvent().subscribe(() => {
      this.update();
    });
  }

  update() {
    this.resetParameters();
    this.ngOnInit();
  }

  ngOnInit() {
    this.folder = this.activatedRoute.snapshot.paramMap.get('id');
    this.checkCountry();
    this.checkCategory();
    this.checkSelectionInEverything();
    this.loadData();
  }

  checkCountry() {
    this.country = this.app.getCountry();
  }

  checkCategory() {
    this.category = this.app.getCategory();
  }

  checkSelectionInEverything() {
    this.language = this.app.getLanguage();
    this.from = this.app.getFrom();
    this.to = this.app.getTo();
    this.sortBy = this.app.getSortBy();
  }

  loadData() {
    if (this.search != '' || this.folder == 'top-headlines') {
      this.newsService.getData(this.folder, this.country, this.category, this.search, this.page, this.language, this.from, this.to, this.sortBy).subscribe(data => {
        // initial load of the data
        console.log(this.page);
        console.log(this.clickEventsubscription);
        if (this.page == 1) {
          this.data = data;
          console.log(data);
        }
        // append next articles to the data array
        else {
          let arr: any[] = data['articles'];

          for (let i = 0; i < data['articles'].length; i++) {
            this.data.articles.push(arr[i]);
          }
          this.checkIfAllArtriclesAreLoaded();
        }
      });
    }
  }

  moreData(event) {
    this.page++;
    this.loadData();

    setTimeout(() => {
      event.target.complete();
      // App logic to determine if all data is loaded
      // and disable the infinite scroll
    }, 500);
  }

  doRefresh(event) {
    this.resetParameters();
    this.loadData();

    setTimeout(() => {
      event.target.complete();
    });
  }

  resetParameters() {
    this.data = null;
    this.page = 1;
    this.country = '';
    this.category = '';
    this.search = '';
    this.language = '';
    this.sortBy = '';
    this.from = null;
    this.to = null;
    this.showInfiniteScroll = true;
  }

  checkIfAllArtriclesAreLoaded() {
    if (this.data['articles'].length >= this.data.totalResults) this.showInfiniteScroll = false;
  }

  async presentModal(article) {
    this.newsService.currentArticle = article;
    const modal = await this.modalController.create({
      component: ArticlePage,
      cssClass: 'my-custom-class'
    });
    return await modal.present();
  }


}

这里是我的 EventListenerService 的代码:

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';

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

  private subject = new Subject<any>();

  sendClickEvent() {
    this.subject.next();
  }

  getClickEvent(): Observable<any> {
    return this.subject.asObservable();
  }

}

【问题讨论】:

  • resetParameters 是同步函数,必须在调用 ngOnInit 之前完全运行?
  • @Ashu 是的,必须完全调用
  • 如果它完全运行有什么问题?
  • 我认为 resetParametes 会变慢或可能无法正常工作,因为如果参数页面 == 1,我只会在 ngOnInit 中加载数据,但如果我记录此内容,则页面是 2 或更高的 eveytime.. .@阿舒
  • 问题出在其他地方。我不知道您为什么要尝试实现这一目标,但在您的代码中调用 ngOnInit() 是一个糟糕的主意。 Angular 会为您提供有关组件何时初始化的信息,您暂时不能强制组件自行初始化。您可能希望将另一个 init() 函数与 detectChanges 策略 OnPush 一起使用。

标签: javascript angular typescript ionic-framework


【解决方案1】:

当指令被实例化时,ngOnInit 只被调用一次。您可以将 ngOnInit 中的代码移动到另一个函数并调用它;

【讨论】:

  • 我已经更新了我在另一个函数中调用它但仍然无法正常工作的代码
  • 你是在某处调用 sendClickEvent 方法吗?
  • 是的,我用其他方法调用它,这应该可以工作:)
  • 是的,这就是问题所在 :) 但昨天它还没有完全更新 ionic 服务,所以我没有在网站上看到更改:/ THX
猜你喜欢
  • 2020-02-25
  • 2017-10-08
  • 2019-05-10
  • 2021-06-08
  • 2021-05-06
  • 1970-01-01
  • 2020-02-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多