使用async/await与JavaScript类时出现TypeError问题排查
问题解决:类方法中this指向丢失导致的TypeError
错误原因
你遇到的TypeError: Cannot read properties of undefined (reading 'dateFromNowInMinutes'),核心原因是类方法的this指向丢失:
在getEvents方法中,使用this.authorize().then(this.listEvents)传递listEvents函数时,该函数的this并没有绑定到GoogleCalendar的实例上。当Promise回调执行listEvents时,this默认指向undefined(严格模式下),自然无法调用类的dateFromNowInMinutes方法。
另外还有一个隐藏问题:authorize方法中调用saveCredentials(client)时,遗漏了this,会导致saveCredentials未定义的错误。
修复方案
方案1:使用箭头函数绑定this(推荐)
修改getEvents方法,通过箭头函数保留类实例的this指向:
async getEvents() { return await this.authorize().then(auth => this.listEvents(auth)).catch(console.error); }
方案2:使用bind绑定this
直接将listEvents方法的this绑定到类实例:
async getEvents() { return await this.authorize().then(this.listEvents.bind(this)).catch(console.error); }
方案3:构造函数中预先绑定方法
如果类中有多个方法需要保持this指向,可以在构造函数中统一绑定:
class GoogleCalendar { constructor() { this.listEvents = this.listEvents.bind(this); } // 其他方法不变 async getEvents() { return await this.authorize().then(this.listEvents).catch(console.error); } }
修复隐藏的saveCredentials调用问题
修改authorize方法中的saveCredentials调用,加上this:
async authorize() { let client = await this.loadSavedCredentialsIfExist(); if (client) { return client; } client = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); if (client.credentials) { await this.saveCredentials(client); // 加上this } return client; }
修正后的关键代码片段
class GoogleCalendar { async getEvents() { // 使用箭头函数绑定this return await this.authorize().then(auth => this.listEvents(auth)).catch(console.error); } async authorize() { let client = await this.loadSavedCredentialsIfExist(); if (client) { return client; } client = await authenticate({ scopes: SCOPES, keyfilePath: CREDENTIALS_PATH, }); if (client.credentials) { // 修复saveCredentials调用 await this.saveCredentials(client); } return client; } // 其他方法保持不变 }
内容的提问来源于stack exchange,提问作者Brad Parks
相关产品推荐
相关产品推荐

