【问题标题】:Accessing an observable stream after it has completed in Angular 2?在 Angular 2 中完成后访问可观察的流?
【发布时间】:2017-11-26 01:42:10
【问题描述】:

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

主页组件

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();
});

}

App 组件中的代码打开数据库

openDB(dbName: string) {

// 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.'))
  }

);

}

【问题讨论】:

    标签: angular observable indexeddb


    【解决方案1】:

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

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

    一旦理解了这一点,如果您需要在应用加载时在组件中提供 db 的数据,您可以使用 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 路由器 Resolve。

    【讨论】:

    • 嗨,Rob,非常感谢您回答我的问题。在过去的几天里,我一直在尝试实施答案。发生的一件事是整个应用程序加载到一个空白的白色屏幕中,我在控制台或终端中没有收到任何错误。我查看了 APP_INITIALIZER 的其他案例,但仍然有点迷茫。
    • 我刚刚开始工作!查看了您的存储库中的应用程序并为 IndexedDB 提供了它,它完美地工作,能够在应用程序加载时获取第一个项目。再次非常感谢!
    猜你喜欢
    • 2017-10-12
    • 1970-01-01
    • 2019-03-25
    • 2020-06-24
    • 2017-06-11
    • 2020-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多