React Native集成Facebook登录后GraphRequest间歇性触发只读属性赋值错误
我之前在集成React Native Facebook登录时也碰到过这个一模一样的间歇性问题,折腾了好一阵才找到问题根源,结合你的代码来看,主要问题出在GraphRequestManager实例的复用上。
问题原因分析
FB的GraphRequestManager在调用start()之后,内部的一些状态属性会被标记为只读。如果像你这样在构造函数里初始化一个全局的requestManager实例,每次调用fetchProfile都复用它,当异步请求存在竞态条件时(比如登录成功后快速多次调用获取资料,或者前一个请求还没处理完就发起新请求),就会尝试给已经变成只读的属性赋值,从而触发这个错误。
具体解决方案
1. 每次请求创建新的GraphRequestManager实例(最推荐)
放弃复用全局的requestManager,每次调用fetchProfile时新建一个实例,从根源避免状态冲突:
async fetchProfile() { return new Promise((resolve, reject) => { // 明确指定需要获取的字段,避免冗余数据,也能确保拿到你需要的信息 const requestParams = { parameters: { fields: { string: 'id,name,email' } } }; const request = new GraphRequest( '/me', requestParams, (error, result) => { if (result) { const profile = { ...result, avatar: `https://graph.facebook.com/${result.id}/picture?type=large` }; resolve(profile); } else { reject(error); } } ); // 每次请求都新建一个GraphRequestManager new GraphRequestManager().addRequest(request).start(); }); }
同时可以删除构造函数里的this.requestManager = new GraphRequestManager(),因为已经不需要复用了。
2. 升级react-native-fbsdk到最新稳定版
部分旧版本的Facebook SDK本身存在这个只读属性的bug,升级到最新版可能直接解决问题。执行以下命令更新:
# npm npm update react-native-fbsdk # yarn yarn upgrade react-native-fbsdk
注意同步更新iOS和Android端的原生SDK依赖(iOS更新Pod,Android更新build.gradle里的依赖版本)。
3. 若坚持复用Manager,需手动清理请求(不推荐)
如果一定要复用全局的requestManager,每次发起新请求前先清空之前的请求,不过这种方式仍然存在异步竞态的风险:
async fetchProfile() { return new Promise((resolve, reject) => { const request = new GraphRequest(...); // 先清空之前的请求 this.requestManager.clearRequests(); this.requestManager.addRequest(request).start(); }); }
验证修改
修改完成后,多次测试登录并获取用户资料,尤其是快速连续操作的场景,应该不会再出现这个间歇性的TypeError了。
内容的提问来源于stack exchange,提问作者Exception

