Ionic Storage : TypeError: Cannot read property 'get' of undefined
Ionic Storage : TypeError: Cannot read property 'get' of undefined
我正在使用 Ionic Storage 在长 运行 上存储数据。现在我想在转到统计页面时检索数据,所以我调用了我创建的服务并在统计页面的 ngOnInit 中编写了方法,但它无法识别存储的实例 class 如果我正确理解了这个问题,但奇怪的是,当我在 ionViewWillEnter() 中编写方法时它确实有效。我使 ngOnInit 和 ionViewWillEnter 都异步,但我仍然收到 ngOnInit 的错误。如果我没记错的话,我可以使用 ionViewWillEnter 技巧,它类似于在我的用例中调用 ngOnInit 中的方法,但我仍然很好奇为什么它会给我带来错误...
统计页面的TS:
import { StatsService } from './../service/stats.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-statistics',
templateUrl: './statistics.page.html',
styleUrls: ['./statistics.page.scss'],
})
export class StatisticsPage implements OnInit {
testsAmount: any = 0;
constructor(public statsService: StatsService) {}
addJohn(){
this.statsService.set("1", "john");
}
removeAll(){
this.statsService.clearAll();
}
async getJohn(){
console.log(await this.statsService.get("1"));
}
async ngOnInit() {
await this.statsService.set("testSetngOnInit", "blabla");
console.log("testSet initialized from the ngOnInit");
console.log(await this.statsService.get("testSetngOnInit"));
}
async ionViewWillEnter(){
await this.statsService.set("testSetionViewWillEnter", "blabla");
console.log("testSet initialized from the ionViewWillEnter");
console.log(await this.statsService.get("testSetionViewWillEnter"));
}
}
服务的 TS:
import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage-angular';
import * as CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';
@Injectable({
providedIn: 'root'
})
export class StatsService {
// private _storage: Storage | null = null;
private _storage: Storage;
constructor(public storage: Storage) {
this.init();
}
async init() {
// If using, define drivers here: await this.storage.defineDriver(/*...*/);
await this.storage.defineDriver(CordovaSQLiteDriver);
const storage = await this.storage.create();
this._storage = storage;
}
async keyExistence(key: string){
if(await this.get(key) == null){
return false;
}
else{
return true;
}
}
// Create and expose methods that users of this service can
// call, for example:
async set(key: string, value: any) {
await this._storage?.set(key, value);
}
async clearAll() {
await this._storage.clear();
}
async get(key: string) {
return await this._storage.get(key);
}
}
这就是我在控制台中得到的:
还有我的 IndexDB:
提前致谢!
错误消息表明 stats.service.ts 中的第 44 行是导致问题的行。您的组件 ngOnInit
确实在访问服务实例,但服务本身失败了。我想这是因为 StatsService
的构造函数正在调用 this.init();
,但构造函数没有等待它(我认为它不能)。因此,当您尝试尽早访问它时(在 ngOnInit 中)this._storage
尚未初始化。
statsService.set
似乎成功的原因是因为该方法调用 this._storage?.set(key, value)
- 注意 ?
这是一个 null 条件,意味着如果 _storage
为 null 那么整个表达式的计算结果为 null
.
我不确定,但我假设 ionViewWillEnter
在组件生命周期的后期被调用,并且统计服务构造函数有足够的时间来完全初始化。另一方面,ngOnInit
在组件构造函数之后立即调用。
好的,我找到答案了!这个其实解决起来很简单,傻到没想到。。。
因此,与其在自己的 class 中实例化服务,不如在使用它的 class 中实例化它,所以在我的例子中:
我在服务构造函数中的内容:
constructor(public storage: Storage) {
this.init();
}
但问题是构造函数不能使用异步语句,所以你不能告诉你的 class 等待它,所以你需要在 class 的 ngOnInit 中初始化使用它:
我的页面使用该服务:
async ngOnInit() {
await this.statsService.init();
}
希望这对某些人有所帮助:)
在您的 AppComponent 中调用 init 以创建一个存储实例。这应该只调用一次。
export class AppComponent implements OnInit,{
constructor(
private storage: StorageService
) {}
async ngOnInit() {
await this.storage.init();
}
我正在使用 Ionic Storage 在长 运行 上存储数据。现在我想在转到统计页面时检索数据,所以我调用了我创建的服务并在统计页面的 ngOnInit 中编写了方法,但它无法识别存储的实例 class 如果我正确理解了这个问题,但奇怪的是,当我在 ionViewWillEnter() 中编写方法时它确实有效。我使 ngOnInit 和 ionViewWillEnter 都异步,但我仍然收到 ngOnInit 的错误。如果我没记错的话,我可以使用 ionViewWillEnter 技巧,它类似于在我的用例中调用 ngOnInit 中的方法,但我仍然很好奇为什么它会给我带来错误...
统计页面的TS:
import { StatsService } from './../service/stats.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-statistics',
templateUrl: './statistics.page.html',
styleUrls: ['./statistics.page.scss'],
})
export class StatisticsPage implements OnInit {
testsAmount: any = 0;
constructor(public statsService: StatsService) {}
addJohn(){
this.statsService.set("1", "john");
}
removeAll(){
this.statsService.clearAll();
}
async getJohn(){
console.log(await this.statsService.get("1"));
}
async ngOnInit() {
await this.statsService.set("testSetngOnInit", "blabla");
console.log("testSet initialized from the ngOnInit");
console.log(await this.statsService.get("testSetngOnInit"));
}
async ionViewWillEnter(){
await this.statsService.set("testSetionViewWillEnter", "blabla");
console.log("testSet initialized from the ionViewWillEnter");
console.log(await this.statsService.get("testSetionViewWillEnter"));
}
}
服务的 TS:
import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage-angular';
import * as CordovaSQLiteDriver from 'localforage-cordovasqlitedriver';
@Injectable({
providedIn: 'root'
})
export class StatsService {
// private _storage: Storage | null = null;
private _storage: Storage;
constructor(public storage: Storage) {
this.init();
}
async init() {
// If using, define drivers here: await this.storage.defineDriver(/*...*/);
await this.storage.defineDriver(CordovaSQLiteDriver);
const storage = await this.storage.create();
this._storage = storage;
}
async keyExistence(key: string){
if(await this.get(key) == null){
return false;
}
else{
return true;
}
}
// Create and expose methods that users of this service can
// call, for example:
async set(key: string, value: any) {
await this._storage?.set(key, value);
}
async clearAll() {
await this._storage.clear();
}
async get(key: string) {
return await this._storage.get(key);
}
}
这就是我在控制台中得到的:
还有我的 IndexDB:
提前致谢!
错误消息表明 stats.service.ts 中的第 44 行是导致问题的行。您的组件 ngOnInit
确实在访问服务实例,但服务本身失败了。我想这是因为 StatsService
的构造函数正在调用 this.init();
,但构造函数没有等待它(我认为它不能)。因此,当您尝试尽早访问它时(在 ngOnInit 中)this._storage
尚未初始化。
statsService.set
似乎成功的原因是因为该方法调用 this._storage?.set(key, value)
- 注意 ?
这是一个 null 条件,意味着如果 _storage
为 null 那么整个表达式的计算结果为 null
.
我不确定,但我假设 ionViewWillEnter
在组件生命周期的后期被调用,并且统计服务构造函数有足够的时间来完全初始化。另一方面,ngOnInit
在组件构造函数之后立即调用。
好的,我找到答案了!这个其实解决起来很简单,傻到没想到。。。 因此,与其在自己的 class 中实例化服务,不如在使用它的 class 中实例化它,所以在我的例子中:
我在服务构造函数中的内容:
constructor(public storage: Storage) {
this.init();
}
但问题是构造函数不能使用异步语句,所以你不能告诉你的 class 等待它,所以你需要在 class 的 ngOnInit 中初始化使用它:
我的页面使用该服务:
async ngOnInit() {
await this.statsService.init();
}
希望这对某些人有所帮助:)
在您的 AppComponent 中调用 init 以创建一个存储实例。这应该只调用一次。
export class AppComponent implements OnInit,{
constructor(
private storage: StorageService
) {}
async ngOnInit() {
await this.storage.init();
}