该视图包含以下元素:
RewriteRule ^(.*)$-registration category.php?link=$1 [NC,L,QSA]
调用组件方法时:
<div *ngIf="showMe">Hello</div>
该元素在视图中显示在所有downloadDemo(): void {
this.download$ = this.downloadService.downloadUrlAsBlobWithProgressAndSaveInFile('assets/skypeforlinux-64.deb', 'demo')
this.download$.subscribe((download: Download) => {
this.showMe = true;
console.log('Progress: ' + download.progress);
})
}
记录器之前。这就是应该的方式。这种基于HTTP的下载效果很好。
但是,调用组件方法时:
Progress
该元素在所有downloadSoundtrack(soundtrack: Soundtrack): void {
const fileName: string = soundtrack.name + '.' + MIDI_FILE_SUFFIX;
const progress$: Observable<ProgressTask<Uint8Array>> = this.midiService.progressiveCreateSoundtrackMidi(soundtrack);
this.download$ = this.downloadService.downloadObservableDataAsBlobWithProgressAndSaveInFile(progress$, fileName);
this.download$.subscribe((download: Download) => {
this.showMe = true;
console.log('Progress: ' + download.progress);
})
}
记录器之后最后在视图中显示。这不是应该的。此基于Progress
的自定义可观察项无法正常工作。实际上,该元素应该显示在所有ReplaySubject
记录器之前而不是之后。
我想看看是否有一个订阅呼叫被阻止。
所以我将两种方法更改为:
Progress
以下是调用downloadSoundtrack(soundtrack: Soundtrack): void {
const fileName: string = soundtrack.name + '.' + MIDI_FILE_SUFFIX;
const progress$: Observable<ProgressTask<Uint8Array>> = this.midiService.progressiveCreateSoundtrackMidi(soundtrack);
this.download$ = this.downloadService.downloadObservableDataAsBlobWithProgressAndSaveInFile(progress$, fileName);
this.showMe = true;
this.download$.subscribe((download: Download) => {
console.log('Progress: ' + download.progress);
});
console.log('Call done');
}
downloadDemo(): void {
this.download$ = this.downloadService.downloadUrlAsBlobWithProgressAndSaveInFile('assets/skypeforlinux-64.deb', 'demo')
this.showMe = true;
this.download$.subscribe((download: Download) => {
console.log('Progress: ' + download.progress);
});
console.log('Call done');
}
方法时的记录器:
downloadDemo()
我们可以看到Progress: 0
Call done
Progress: 0
Progress: 0
Progress: 2
Progress: 3
通话没有阻塞。
以下是调用subscribe()
方法时的记录器:
downloadSoundtrack()
我们可以看到Progress: 96
Progress: 97
Progress: 100
Call done
通话被阻止。
添加明确的subscribe()
调用没有区别:
this.detectChanges();
它仍然显示在所有downloadSoundtrack(soundtrack: Soundtrack): void {
const fileName: string = soundtrack.name + '.' + MIDI_FILE_SUFFIX;
const progress$: Observable<ProgressTask<Uint8Array>> = this.midiService.progressiveCreateSoundtrackMidi(soundtrack);
this.download$ = this.downloadService.downloadObservableDataAsBlobWithProgressAndSaveInFile(progress$, fileName);
this.download$.subscribe((download: Download) => {
this.showMe = true;
this.detectChanges();
console.log('Progress: ' + download.progress);
})
}
记录器之后。
我还尝试了一些显式订阅来代替模板中的Progress
,但是它没有任何帮助:
*ngIf="download$ | async as download"
长期运行的服务:
downloadInProgress(soundtrack: Soundtrack): boolean {
let inProgress: boolean = false;
if (soundtrack.download) {
if (soundtrack.download.progress > 0 && soundtrack.download.progress < 100) {
inProgress = true;
} else if (soundtrack.download.progress == 100) {
console.log('complete');
soundtrack.download = undefined;
}
}
console.log('inProgress ' + inProgress);
return inProgress;
}
有50ms的睡眠调用,这会减慢文件创建的速度,以便留出足够的时间。
下载服务的实现基于this article
我正在使用Angular 9.1.0
答案 0 :(得分:0)
为简单起见,我建议改用更具反应性的状态驱动方法,在此方法中,您可以执行以下操作:
1。
将soundtracks
从数组更改为public readonly soundtracks: Observable<Soundtrack[]> = this.soundtracksSubject.asObservable()
,以使UI可以注册更改。 this.soundtracksSubject
是private readonly soundtracksSubject: BehaviorSubject<Soundtrack[]> = new BehaviorSubject([]);
,然后可以用来触发soundtracks
的观察者刷新。收到HTTP响应时,您无需设置this.soundtracks = soundtracks;
而是调用this.soundtracksSubject.next(soundtracks))
。
在进行实际下载(soundtrack.download = download;
)时,不仅要在更改后更改模型,还必须再次调用主题以将模型中的更改传播给侦听器:
const updatedSoundtracks: Soundtrack[] = this.soundtracksSubject.value.map(existingSoundtrack => existingSoundtrack);
const soundtrack: Soundtrack = updatedSoundtracks.find(existingSoundtrack => soundtrack.name === existingSoundtrack.name); // Or whatever identifies your soundtrack
if (soundtrack) {
soundtrack.download = download;
this.soundtracksSubject.next(updatedSoundtracks);
}
将用户界面从<tr *ngFor="let soundtrack of soundtracks">
更改为<tr *ngFor="let soundtrack of soundtracks | async">
,以解析Observable
以便在Angular组件中使用它。这也意味着您的组件将注册soundtracks
上的更改,并在有人调用主题/可观察对象时得到通知。
Observable
和BehaviorSubject
都是RxJS概念(import {BehaviorSubject, Observable} from "rxjs/index";
),值得研究,因为它们使您的生活变得更加轻松。