使用 Promise 在 Angular 和 Ionic 的页面上显示用户信息时出现以下错误
Posted
技术标签:
【中文标题】使用 Promise 在 Angular 和 Ionic 的页面上显示用户信息时出现以下错误【英文标题】:Getting following error while displaying user information on a page in Angular and Ionic with Promise 【发布时间】:2019-05-30 15:15:16 【问题描述】:在我的应用程序和AccountSettingsPage
上,我从SQLite DB
获取用户数据并将其显示在Ionic
页面上。但是,我收到此错误。
错误:
TypeError: Cannot read property 'name' of undefined
at Object.eval [as updateRenderer] (ng:///AppModule/AccountSettingsPage.ngfactory.js:87:37)
at Object.debugUpdateRenderer [as updateRenderer] (http://192.168.0.4:8100/build/vendor.js:15109:21)
at checkAndUpdateView (http://192.168.0.4:8100/build/vendor.js:14223:14)
at callViewAction (http://192.168.0.4:8100/build/vendor.js:14569:21)
at execComponentViewsAction (http://192.168.0.4:8100/build/vendor.js:14501:13)
at checkAndUpdateView (http://192.168.0.4:8100/build/vendor.js:14224:5)
at callViewAction (http://192.168.0.4:8100/build/vendor.js:14569:21)
at execEmbeddedViewsAction (http://192.168.0.4:8100/build/vendor.js:14527:17)
at checkAndUpdateView (http://192.168.0.4:8100/build/vendor.js:14219:5)
at callViewAction (http://192.168.0.4:8100/build/vendor.js:14569:21)
account-settings.ts
export class AccountSettingsPage
currentUser: User;
constructor(private navCtrl: NavController, private navParams: NavParams, private userProvider: UserProvider)
this.getCurrentUserDetails("ab@cd.com");
getCurrentUserDetails(email: string)
this.userProvider.getUserByEmail(email)
.then((currentUser: User) =>
this.currentUser = currentUser;
console.log("data: " + JSON.stringify(currentUser));
)
.catch(e => console.error(JSON.stringify(e)));
user.ts(用户提供者)
getUserByEmail(email: string): Promise<User>
return this.databaseProvider.getDatabase().then(database =>
return database.executeSql(SQL_SELECT_USER_BY_EMAIL, [email])
.then((data) =>
let user: User;
//loop through all the records and populate the user object. Should be only 1
for (let i = 0; i < data.rows.length; i++)
user =
id: data.rows.item(i).id,
name: data.rows.item(i).name,
email: data.rows.item(i).email,
password: data.rows.item(i).password,
confirmPassword: data.rows.item(i).password,
phone: data.rows.item(i).phone,
street1: data.rows.item(i).street1,
street2: data.rows.item(i).street2,
city: data.rows.item(i).city,
state: data.rows.item(i).state,
zip: data.rows.item(i).zip,
active: data.rows.item(i).active
;
//return the populated user object back
return user;
);
);
account-settings.html(页面)
<ion-header>
<ion-navbar>
<ion-title>Account Settings</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-label>Name: currentUser.name</ion-label>
<ion-label>Email: currentUser.email</ion-label>
<ion-label>Password: "*****"</ion-label>
<ion-label>Phone: currentUser.name</ion-label>
<ion-label>Street 1: currentUser.street1</ion-label>
<ion-label>Street 2: currentUser.street1</ion-label>
<ion-label>City: currentUser.city</ion-label>
<ion-label>State: currentUser.state</ion-label>
<ion-label>Zip: currentUser.zip</ion-label>
</ion-list>
<button ion-button (click)="logout()">Logout</button>
</ion-content>
【问题讨论】:
你真的是指data.rows.item(i)
吗?假设您循环通过data.rows
使用data.rows[i]
会更有意义,但是根本不循环并只使用data.rows[0]
的属性会更有意义(如果存在;如果不存在则抛出) .
我还是 JS 和移动开发领域的新手。将尝试您的建议@Roamer-1888
【参考方案1】:
在创建视图时,控制器中的 currentUser
为 undefined
,直到从数据库中获取。
如果 currentUser
未定义,您应该在 html 中添加 *ngIf 指令以防止显示。
<ion-content *ngIf="currentUser" padding>
<ion-list>
<ion-label>Name: currentUser.name</ion-label>
<!-- ... -->
</ion-list>
<button ion-button (click)="logout()">Logout</button>
</ion-content>
然后更新 UserProdiver 以从承诺中实际返回一个值:
getUserByEmail(email: string): Promise<User>
return new Promise((resolve, reject) =>
this.databaseProvider.getDatabase().then(database =>
database.executeSql(SQL_SELECT_USER_BY_EMAIL, [email])
.then((data) =>
let user: User;
//loop through all the records and populate the user object. Should be only 1
for (let i = 0; i < data.rows.length; i++)
user =
id: data.rows.item(i).id,
name: data.rows.item(i).name,
email: data.rows.item(i).email,
password: data.rows.item(i).password,
confirmPassword: data.rows.item(i).password,
phone: data.rows.item(i).phone,
street1: data.rows.item(i).street1,
street2: data.rows.item(i).street2,
city: data.rows.item(i).city,
state: data.rows.item(i).state,
zip: data.rows.item(i).zip,
active: data.rows.item(i).active
;
//return the populated user object back
return resolve(user);
);
);
);
【讨论】:
【参考方案2】:尝试使用*ngIf 仅在currentUser
成功加载后显示用户数据。由于currentUser
未使用您正在渲染和异步加载的所有这些属性的默认值进行初始化,因此您可以使用此结构指令来避免尝试访问未定义对象的这些属性,直到成功加载/解析:
<ion-content *ngIf=“currentUser” padding>
<ion-list>
<ion-label>Name: currentUser.name</ion-label>
<ion-label>Email: currentUser.email</ion-label>
<ion-label>Password: "*****"</ion-label>
<ion-label>Phone: currentUser.name</ion-label>
<ion-label>Street 1: currentUser.street1</ion-label>
<ion-label>Street 2: currentUser.street1</ion-label>
<ion-label>City: currentUser.city</ion-label>
<ion-label>State: currentUser.state</ion-label>
<ion-label>Zip: currentUser.zip</ion-label>
</ion-list>
<button ion-button (click)="logout()">Logout</button>
</ion-content>
您可以通过使用带有*ngIf
的else
语句来扩展此概念,以在数据加载时显示加载消息或类似信息:
<ion-content *ngIf=“currentUser; else loadingCurrentUser” padding>
<ion-list>
<ion-label>Name: currentUser.name</ion-label>
<ion-label>Email: currentUser.email</ion-label>
<ion-label>Password: "*****"</ion-label>
<ion-label>Phone: currentUser.name</ion-label>
<ion-label>Street 1: currentUser.street1</ion-label>
<ion-label>Street 2: currentUser.street1</ion-label>
<ion-label>City: currentUser.city</ion-label>
<ion-label>State: currentUser.state</ion-label>
<ion-label>Zip: currentUser.zip</ion-label>
</ion-list>
<button ion-button (click)="logout()">Logout</button>
</ion-content>
<ng-template #loadingCurrentUser>
Loading...
</ng-template>
最后考虑在Angular生命周期钩子OnInit而不是构造函数中执行这个调用,这是初始化任务的理想位置,例如这个数据库调用:
export class AccountSettingsPage implements OnInit
currentUser: User;
constructor(private navCtrl: NavController, private navParams: NavParams, private userProvider: UserProvider)
ngOnInit(): void
this.getCurrentUserDetails("ab@cd.com");
getCurrentUserDetails(email: string)
this.userProvider.getUserByEmail(email)
.then((currentUser: User) =>
this.currentUser = currentUser;
console.log("data: " + JSON.stringify(currentUser));
)
.catch(e => console.error(JSON.stringify(e)));
希望对您有所帮助!
【讨论】:
以上是关于使用 Promise 在 Angular 和 Ionic 的页面上显示用户信息时出现以下错误的主要内容,如果未能解决你的问题,请参考以下文章
在Angular 2中拒绝Promise时未处理的Promise拒绝[重复]
在 Angular 中,如何在使用 async/await 时处理 Promise 拒绝
Promise.all 的 then() 函数在 Promise 完成之前执行 - Ionic/Angular
angular ui-router 1.0.3 和 angular.js 1.6.4 似乎使用了错误的 Promise 类型?