识别订阅中 concat 的特定可观察对象

Identify specific observable of a concat in subscription

我正在尝试按顺序/交替下载多个文件。下载文件后,我想根据文件的 id 在它旁边显示一个成功图标。由于文件很大,这将允许简单的下载管理并在出现错误时重试特定文件。

我正在做类似的事情:

var finalObservable: Observable<any> = null;

for (var i = 0; i < this.files.length; i++) {
    var currentFileId = this.files[i].fileId;
    var currentObservable = this.service.getResourceObservable(this.files[i].downloadLink)
                            .map(data => {return {fileId: currentFileId, result:data}});
    if (finalObservable == null) {
        finalObservable = currentObservable;
    } else {
        finalObservable = finalObservable.merge(currentObservable);
    }
}

finalObservable.subscribe(resp => {
    this.downloadService.download(resp.result);
    for (var i = 0; i < this.files.length; i++) {
        if (this.files[i].fileId == resp.fileId)  {
            this.files[i].downloaded = true ;
        }
    }
});

发生的情况是发送的 fileId 总是 this.files[this.files.length-1].fileId。所以基本上,只有最后一个文件获得 downloaded = true

我不明白为什么...你能帮忙吗?

注:我是基于这个 question/answer 这里

TL;DR

尝试使用 let 关键字而不是 var:

来定义 currentFileId
let currentFileId = this.files[i].fileId;

说明

currentFileId 是在循环中用 var 关键字定义的(它定义了一个变量在 整个函数作用域,不考虑块作用域)

for (var i = 0; i < this.files.length; i++) {
    var currentFileId = this.files[i].fileId;
    var currentObservable = this.service.getResourceObservable(this.files[i].downloadLink)
                            .map(data => {return {fileId: currentFileId, result:data}});

在循环体的第二行创建闭包,每个闭包 获取对 相同变量 currentFileId 的引用。并且在循环之后,最后一个文件的fileId存储在currentFileId中,并且在调用函数时每个闭包使用相同的值。

详细的解释可以看这个回答