React Native自定义类无法设置属性问题求助
问题分析与解决方案
嘿,这个问题我之前也碰到过!核心原因其实很简单:数据库查询是异步操作,你调用UserInfo.username的时候,异步任务还没跑完,自然拿不到更新后的值。
为什么会出现这种情况?
db.transaction和tx.executeSql都是非阻塞的异步方法——构造函数调用getUserInfo后,代码会立刻继续执行,而数据库查询还在后台慢悠悠地跑。这时候你去访问username,它还是构造函数里初始化的空字符串;等控制台打印出row.id的时候,异步任务才完成,但这时候你早就已经读取过username了。
怎么解决?
这里给你几个实用的方案,按需选就行:
方案1:用Promise封装,等待数据加载完成
把getUserInfo改成返回Promise,这样外部可以明确等待数据就绪后再使用:
class UserInfo { constructor(props) { this.username = "" // 初始化时启动加载,把Promise存起来供外部等待 this.loadPromise = this.getUserInfo() } getUserInfo = () => { return new Promise((resolve, reject) => { db.transaction((tx) => { tx.executeSql( 'SELECT * FROM users', [], (tx, results) => { const row = results.rows.item(0); console.log("UserID: " + row.id) this.username = row.id resolve(row.id) // 通知Promise加载完成 }, (error) => reject(error) // 捕获查询错误 ); }); }) } } export default (new UserInfo())
调用的时候要等Promise完成:
import UserInfo from './UserInfo' UserInfo.loadPromise.then(() => { console.log(UserInfo.username) // 这里就能拿到正确的ID了 }).catch(err => { console.error('加载用户信息失败:', err) })
方案2:用回调函数处理结果
如果你的项目还没用到Promise,回调函数也是个稳妥的选择:
class UserInfo { constructor(props) { this.username = "" } getUserInfo = (callback) => { db.transaction((tx) => { tx.executeSql( 'SELECT * FROM users', [], (tx, results) => { const row = results.rows.item(0); this.username = row.id callback(null, row.id) // 成功时返回结果 }, (error) => callback(error, null) // 失败时返回错误 ); }); } } export default (new UserInfo())
调用示例:
import UserInfo from './UserInfo' UserInfo.getUserInfo((err, userId) => { if (!err) { console.log(UserInfo.username) // 或者直接用userId参数 } else { console.error('查询出错:', err) } })
方案3:观察者模式(适合多页面监听数据变化)
如果多个页面需要在用户信息更新后自动刷新,观察者模式会很方便:
class UserInfo { constructor(props) { this.username = "" this.listeners = [] this.getUserInfo() } getUserInfo = () => { db.transaction((tx) => { tx.executeSql('SELECT * FROM users', [], (tx, results) => { const row = results.rows.item(0); this.username = row.id // 通知所有监听者数据更新了 this.listeners.forEach(listener => listener(this.username)) }); }); } // 添加监听函数 addListener(listener) { this.listeners.push(listener) // 如果已经有数据,立刻触发一次 if (this.username) listener(this.username) } // 移除监听(避免内存泄漏) removeListener(listener) { this.listeners = this.listeners.filter(l => l !== listener) } } export default (new UserInfo())
页面中使用:
import UserInfo from './UserInfo' // 定义更新逻辑 const updateUserUI = (username) => { console.log('当前用户ID:', username) // 这里可以更新页面上的用户信息展示 } // 添加监听 UserInfo.addListener(updateUserUI) // 页面卸载时记得移除监听 // UserInfo.removeListener(updateUserUI)
总结
本质就是要处理异步操作的时机问题——不能在异步任务完成前就去读取它要更新的变量。上面的方案分别对应了"主动等待"、"回调通知"、"自动监听"三种场景,你可以根据自己的项目需求选最顺手的。
内容的提问来源于stack exchange,提问作者DIGITAL JEDI
相关产品推荐
相关产品推荐

