Facebook iOS内置浏览器this.onready TypeError问题排查与修复
排查Facebook登录SDK在iOS FB内置浏览器中的
this.onready is not a function错误 我来帮你拆解这个问题——这个this.onready is not a function错误是Facebook JS SDK在特定环境下的初始化冲突问题,咱们一步步来分析和解决:
问题回顾
你已经集成了Facebook登录功能,但在Facebook iOS应用170-172版本的内置浏览器里,Rollbar捕获到来自https://connect.facebook.net/en_US/sdk.js的错误:
TypeError: this.onready is not a function. (In 'this.onready(a)', 'this.onready' is undefined)
原因分析
这个错误看起来是Facebook SDK内部的回调绑定问题,但触发点通常和咱们的初始化逻辑有关:
- 你的代码在
window.fbAsyncInit中直接同步调用了FB.getLoginStatus和FB.login,而Facebook内置浏览器本身已经带有FB环境,SDK加载流程和普通浏览器不同,直接同步执行方法会导致SDK内部的onready回调还没挂载完成就被触发,从而抛出错误。 - 另外,你使用的SDK版本是v2.8,这个版本比较老旧,对iOS FB内置浏览器的兼容性存在已知bug。
修复方案
方案1:调整初始化逻辑,改用事件订阅替代同步调用
把直接调用FB方法的逻辑改成订阅SDK的auth.statusChange事件,确保在SDK完全就绪后再处理登录状态:
$.ajaxSetup({cache: true}); window.fbAsyncInit = function() { if(typeof FB != 'undefined'){ FB.init({ appId : fb_app_id, cookie : true, xfbml : true, version : 'v2.8' }); // 订阅登录状态变化事件,替代直接同步调用 FB.Event.subscribe('auth.statusChange', function(response) { if (response.status === 'connected') { onLogin(response); } else { // 注意:不要自动触发FB.login,建议交给用户点击登录按钮的交互触发 // 若必须自动触发,添加延迟避免初始化冲突 setTimeout(function() { FB.login(function(response) { onLogin(response); }, {scope: 'user_friends, email'}); }, 100); } }); // 手动触发一次状态检查 FB.getLoginStatus(); } else{ Rollbar.debug("Not loaded base SDK"); return false; } }; (function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) {return;} js = d.createElement(s); js.id = id; js.src = "https://connect.facebook.net/en_US/sdk.js"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); function checkLoginState() { if(typeof FB == 'undefined'){ Rollbar.debug("FB is undefined. Was a problem loading the Facebook resources. Maybe your provider temporarily blocks this resource"); return false; } FB.getLoginStatus(function(response) { onLogin(response); }); }
这样修改的核心是让SDK内部的初始化流程完成后再处理状态,避免提前触发未绑定的onready回调。
方案2:检测FB内置浏览器,避免重复加载SDK
Facebook内置浏览器本身已经包含FB对象,重复加载SDK会导致冲突,我们可以先检测环境,只在非FB内置浏览器中加载SDK:
// 检测是否为Facebook iOS内置浏览器 function isFacebookInAppBrowser() { const userAgent = navigator.userAgent || navigator.vendor || window.opera; return /FBAN|FBAV/.test(userAgent); } $.ajaxSetup({cache: true}); window.fbAsyncInit = function() { if(typeof FB != 'undefined'){ FB.init({ appId : fb_app_id, cookie : true, xfbml : true, version : 'v2.8' }); FB.getLoginStatus(function(response) { if (response.status == 'connected') { onLogin(response); } else { // 建议通过用户交互触发登录,避免自动弹窗被拦截 // FB.login(...); } }); } else{ Rollbar.debug("Not loaded base SDK"); return false; } }; // 仅在非FB内置浏览器中加载SDK if (!isFacebookInAppBrowser()) { (function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) {return;} js = d.createElement(s); js.id = id; js.src = "https://connect.facebook.net/en_US/sdk.js"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); } else { // FB内置浏览器中直接执行初始化(FB对象已存在) if (typeof FB !== 'undefined') { window.fbAsyncInit(); } } function checkLoginState() { if(typeof FB == 'undefined'){ Rollbar.debug("FB is undefined. Was a problem loading the Facebook resources. Maybe your provider temporarily blocks this resource"); return false; } FB.getLoginStatus(function(response) { onLogin(response); }); }
方案3:升级SDK版本到稳定版
你当前使用的v2.8版本已经非常老旧,Facebook后续版本修复了大量特定环境下的兼容性问题,建议升级到最新的稳定版本(比如v18.0),这很可能直接解决这个onready未定义的错误。
额外注意事项
- 不要在
fbAsyncInit中自动调用FB.login,大多数浏览器(包括FB内置浏览器)会拦截自动弹出的登录窗口,而且容易和SDK初始化流程冲突,最好让用户点击登录按钮后再触发登录。 - 确保
onLogin函数在全局作用域中可访问,避免因作用域问题导致其他错误。
内容的提问来源于stack exchange,提问作者Alex Karahanidi
相关产品推荐
相关产品推荐

