订阅后的Angular 2数组具有元素,但长度为0

时间:2018-08-25 19:32:52

标签: javascript angular typescript rxjs observable

我正在使用Angular 2,并且发现了意外的行为。

我有一个数据源类,该类扩展了DataSource,具有两个变量:

private archives = new BehaviorSubject<MyArchive[]>([]);
public archives$: Observable<MyArchive[]> = this.archives.asObservable();
private filteredArchive: MyArchive[];

我在课堂上以这种方式更新档案:

this.archives.next(this.filteredArchive);

在另一个类的外部,我尝试订阅可观察的对象,但是它不起作用:

ngAfterViewInit(): void {

    this.dataSource.archives$.subscribe((archive: Array<MyArchive>) => {

        console.log(archive.length);
        console.log(archive);
        console.log(archive.length);
    }
}

在控制台日志中它打印:

0
<THE ARCHIVE WITH AN OBJECT INSIDE AS IT SHOULD BE, WITH LENGTH = 1>
0

因为长度为0,所以我不能对归档变量进行迭代。

4 个答案:

答案 0 :(得分:2)

在您订阅之前已经发出该值的问题。将可观察对象视为电视流,如果您在电视节目结束后打开电视(在推送数据后订阅),就不会看到电视节目,那么您的数据就像该电视节目上的电视节目一样。如果您希望观察者保留最后一个值,则可以使用“扫描”运算符,如下所示:

export const reducer = () =>

   scan<MyArchive[]>((archive, update) => {
    //update your Archive or simply overwrite the value
    archive = update

    return archive

    }, []);

export class datasource {

   archives$ : Observable<MyArchive[]>;

   archives : Subject<MyArchive[]> = new Subject([]);

   update(newMyArchive: MyArchive[]) {
     this.archives.next(newMyArchive);
    }

   constructor(public http: HttpClient) {

   this.archives$ = this.archives.pipe(
     reducer(),
   //use the shareReplay so all your subscribers get the same values
     shareReplay(1)
     );
  this.archives$.subscribe();
}

,您可以使用数据源类中的update方法更新Arcjive,例如:

this.update(filteredArchive)

答案 1 :(得分:1)

我不确定为什么要重复创建archives$archives。您只需一个BehaviorSubject就可以做到这一点。

我认为您应该这样做:

// Create a BehaviorSubject for MyArchive[]
public archives$: BehaviorSubject<MyArchive[]> = new BehaviorSubject<MyArchive[]>([]);
// Create a private filtered Array for MyArchive.
private filteredArchive: MyArchive[];

然后

this.archives$.next(this.filteredArchive);

答案 2 :(得分:1)

使用此语句时:

console.log(archive);

在控制台中显示对archive对象的引用(请参见the MDN documentation)。当您在控制台中(通过单击箭头)检查对象时,其内容可能与执行console.log语句时的内容不同。

为了查看特定时刻的实际内容,您应该输出对象的字符串表示形式:

console.log(archive.toString());
console.log(JSON.stringify(archive));

您可以练习this stackblitz来查看各种控制台输出。

答案 3 :(得分:0)

我解决了这个问题。 我忘记了this.filteredArchive是由HTTP GET请求更新的。我试图使用forEach在this.filteredArchive中推送数据,但是当接收到所有数据时,我忘记了调用then()。 因此,我试图使用订阅访问尚未准备好的结果。

感谢大家的答复!