在 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。
我一直在编写一个使用 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。