Observable不订阅延迟加载的模块

时间:2020-03-20 22:55:27

标签: angular typescript rxjs

我想知道为什么我的延迟加载模块加载测试组件时不允许测试组件订阅由测试服务注入的可观察对象

index.ts

export { TestComponent } from './test.component';
export { TestModule } from './test.module';

test.component.ts

import { Component, OnInit } from '@angular/core';
import { TestService } from './test.service';
import { Observable } from 'rxjs';

@Component({
    selector: 'test',
    template: `
        <p>{{test | async}}</p>
  `,
})
export class TestComponent {
    test: Observable<number>;
    constructor(private testService: TestService) { 
        this.test = this.testService.getObservable();
    }
}

test.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { TestComponent } from './test.component';
import { TestService } from './test.service';

@NgModule({
    declarations: [TestComponent],
    imports: [
        CommonModule,
    ],
    providers: [TestService]
})
export class TestModule { }

test.service.ts

import { Injectable } from '@angular/core';
import { from, Observable } from 'rxjs';
import { delay } from "rxjs/operators";

@Injectable()
export class TestService {
    getObservable(): Observable<number> {
        return from([...Array(10).keys()].reverse())
            .pipe(
                delay(1000)
            )
    }
}

app.component.ts

import { Component, ViewChild, ViewContainerRef, Compiler, Injector, Type, NgModuleFactory } from '@angular/core';
import { TestModule } from './test';

@Component({
    selector: 'app-root',
    template: `
        <ng-container #vc></ng-container>
  `,
    styles: []
})
export class AppComponent {
    @ViewChild('vc', { read: ViewContainerRef }) containerRef: ViewContainerRef;

    constructor(private compiler: Compiler, private injector: Injector) {
    }

    async ngOnInit(): Promise<void> {
        await this.loadComponent();
    }

    async loadComponent(): Promise<void> {
        const { TestComponent, TestModule } = await import('./test');
        const moduleFactory = await this.loadModuleFactory(TestModule);
        const moduleRef = moduleFactory.create(this.injector);
        const factory = moduleRef.componentFactoryResolver.resolveComponentFactory(TestComponent);
        this.containerRef.createComponent(factory);
    }

    private async loadModuleFactory(moduleFactory: Type<TestModule>): Promise<NgModuleFactory<TestModule>> {
        if (moduleFactory instanceof NgModuleFactory) {
            return moduleFactory;
        } else {
            return await this.compiler.compileModuleAsync(moduleFactory);
        }
    }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

app.module.ts 仅在此处出于完整性考虑。

编译所有这些代码后,不会显示 p 标记之间的文本。

2 个答案:

答案 0 :(得分:0)

好吧,最后,我没有得到所谓的可观察倒计时结果的原因仅仅是一个rxjs问题。 我不明白为什么我的方法行不通:

from([...Array(10).keys()].reverse()).pipe(delay(1000));

对我来说,这是创建倒计时的一种直观方式。 在对stackoverflow进行了一些研究之后,我发现了使其正常工作的一些方法。像这样:

const timer = 10; 
interval(1000).pipe(take(timer), map(time => (timer - 1) - time));

答案 1 :(得分:0)

根据您的原始示例,类似的方法将起作用:

  numbers$: Observable<number> = from(
    Array.from(Array(10).keys()).reverse()
  ).pipe(
    concatMap(n => of(n).pipe(delay(1000))),
    tap(console.log)
  );

几件事:

在TypeScript中,由于以下原因,我无法使用传播运算符:https://github.com/Microsoft/TypeScript/issues/18247

延迟运算符延迟排放的开始,而不延迟排放之间的间隔。

concatMap将为每个发射等待,然后再处理下一个发射。通过将每个数字设为一个可观察的值并将其延迟,然后使用concatMap等待,它将执行递减计数。

就代码的可读性而言,您建议的替代方法似乎更清晰:

  numbers$ = interval(1000).pipe(
    take(10),
    map(time => 9 - time)
  );