在 Angular 2 中完成后访问可观察流?

Accessing an observable stream after it has completed in Angular 2?

我一直在编写一个使用 IndexedDB 的简单应用程序(感谢 Robisim 提供的示例应用程序,我借用了它的代码 https://github.com/robisim74/angular2indexedDB),但我无法异步访问我的组件的对象数组。即使我能够使用 | 遍历 html 页面中的 ITEMS异步管道 - 我似乎无法使用 ts 文件中的对象数组。我试过订阅可观察对象,但它没有成功做任何事情。当可观察对象从 IndexedDB 加载完成时,任何人都可以帮我 select 对象数组中的第一个对象吗?

主页组件

getSchedule() {

this.selectedSchedule = this.entity.schedule[0];

}

获取 ITEMS():可观察的 {

return new Observable((observer: Observer<Array<Item>>) => {


  observer.next(this.entity.schedule);
  console.log(this.entity.schedule);
  observer.complete();
});

}

应用程序组件中的代码打开数据库

openDB(数据库名称:字符串){

// Opens the database.
this.indexedDB.openDBAsync(dbName, 1).forEach(

  // Next.
  (readyState: string) => {

    console.log('IndexedDB service: opening db: ' + readyState);

  }, null

).then(

  () => {

    // Gets all records from "TodoStore".
    this.indexedDB.getAllRecordsAsync("ItemStore").forEach(

      // Next.
      (record: Item) => {

        // Adds next record to the Todos entity.
        if (record != null) {

          this.entity.addItem(record);

        }

      }, null

    ).then(() => console.log('IndexedDB service: obtaining of all records completed.'))
  }

);

}

因为对 IndexedDB 的访问是异步的,所以问题仅出现在 调用 getSchedule 方法时:实际上,如果您从构造函数调用该方法, openDB 方法肯定还没有完成。尝试从按钮调用该方法,您会发现它有效:

<button type="button" (click)="getSchedule()">Get schedule</button>

一旦你理解了这一点,如果你需要数据库的数据在应用程序加载时在组件中可用,你可以,例如,使用 APP_INITIALIZER,它等待条件被满足之前上传应用程序:

AppModule

@Injectable() export class IndexedDB {

    constructor(public indexedDB: IndexedDBService, public entity: Entity) { }

    load(): Promise<void> {
        // Opens the "Angular2IndexedDB" database. If it doesn't exist, it will be created.
        let promise: Promise<any> = new Promise((resolve: any) => {
            this.indexedDB.openDBAsync("Angular2IndexedDB", 1).forEach(
                (readyState: string) => {
                    console.log('IndexedDB service: opening db: ' + readyState);
                }, null
            ).then(
                () => {
                    // Gets all records.
                    this.indexedDB.getAllRecordsAsync("ItemStore").forEach(
                        // Next.
                        (record: Item) => {
                            // Adds next record to the entity.
                            if (record != null) {
                                this.entity.addItem(record);
                            }
                        }, null
                    ).then(() => {
                        resolve(true);
                        console.log('IndexedDB service: obtaining of all records completed.');
                    });
                });
        });

        return promise;
    }
}

export function initIndexedDB(indexedDB: IndexedDB): Function {
    return () => indexedDB.load();
}

@NgModule({
    ...
    providers: [
        IndexedDBService,
        Entity,
        IndexedDB,
        {
            provide: APP_INITIALIZER,
            useFactory: initIndexedDB,
            deps: [IndexedDB],
            multi: true
        }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

并从 AppComponent 中删除 openDB 方法。

如果您需要为特定组件加载数据,您可以使用 Angular router Resolve。