I\'m using the Facebook JS sdk, and I have created a new App today. Everything is configured properly. Using init function like:
window.fbAsyncInit = functio
You are using the cordova-plugin-facebook4 plugin, and that is a custom error message that means that the init hasn't finished when the facebook api function is called. Since the plugin does not give a waitForInitialize
using setTimeout and then retrying the api method is the best bet.
var retryFunc = (iteration) => {
return new Promise((s, f) => facebookConnectPlugin.getLoginStatus(s, f))
.then(authentication => authentication.status === 'connected')
.then(isLoggedIn => {
/* Your Code Here */
})
.catch(failure => {
console.log(`Waiting for Facebook Init. Iteration: ${iteration || 0}`);
if((iteration || 0) < 10) {
return new Promise((s, setTimeout(() => s(), 1000)
.then(() => retryFunc(null, (iteration || 0) + 1);
}
else { return Promise.reject({Error: 'Failed to check login status.', Detail: failure}); }
});
};
retryFunc();
/* Or replace getLoginStatus with your api call. */
I had the same problem, and I think I found the root cause!
In my case, we were injecting FB SDK dynamically to our customer's website. However, some of our customers were already added FB SDK via other plugins. Those plugins have different app id and version.
So depending on latency some plugins call init
before/after ours
If you're the owner of the site where you're injecting the SDK, make sure no other plugins are injecting FB SDK and calling init
different version and app id
If you don't own the site, then at least try to inject the SDK before anyone else and prefer not async
I also reported the same to FB. They told not to call init separately, pass init params directly in the rule. I've attached the code that I use:
if (!document.getElementById("fb-root")) {
// create div required for fb
const fbDiv = document.createElement("div");
fbDiv.id = "fb-root";
document.body.appendChild(fbDiv);
// Run any script after sdk is loaded
window.fbAsyncInit = () => {
//
};
// inject sdk.js
(function(d, script) {
script = d.createElement("script");
script.type = "text/javascript";
script.async = true;
script.src =
"https://connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v3.2&appId=" +
process.env.REACT_APP_FB_APP_ID +
"&autoLogAppEvents=1";
d.getElementsByTagName("head")[0].appendChild(script);
})(document);
}
I got it working by using all.js instead of sdk.js.
In your case, it would look like:
js.src = "//connect.facebook.net/pl_PL/all.js";
instead of
js.src = "//connect.facebook.net/pl_PL/sdk.js";
This was the only fix that would eliminate the error 100% of the time.
You can recreate this error by deleting your FB.init. Which confirms that although the sdk.js had been loaded and the FB namespace existed, FB.init hadn't been called by the time we were trying to use FB methods elsewhere in our scripts.
So we need to ensure that FB.init has been called. I used a similar approach to this answer:
if (typeof(fbApi) === 'undefined') { fbApi = {}; }
fbApi = (function () {
var fbApiInit = false;
var awaitingReady = [];
var notifyQ = function() {
var i = 0,
l = awaitingReady.length;
for(i = 0; i < l; i++) {
awaitingReady[i]();
}
};
var ready = function(cb) {
if (fbApiInit) {
cb();
} else {
awaitingReady.push(cb);
}
};
window.fbAsyncInit = function () {
FB.init({
appId : '<?php echo esc_js( $facebook_app_id ); ?>',
status : true,
cookie : true,
xfbml : true,
version: 'v2.0'
});
fbApiInit = true;
notifyQ();
};
return {
/**
* Fires callback when FB is initialized and ready for api calls.
*/
'ready': ready
};
})();
(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 = "//connect.facebook.net/en_US/sdk.js";
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
Then, elsewhere, any reference to FB can be made like this:
fbApi.ready(function() {
FB.XFBML.parse($("#fb-comments"));
});
We use our own API that does this:
_loadFacebookApi: function(callback) {
logger.info('_loadFacebookApi');
(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";
}(document, 'script', 'facebook-jssdk'));
var fbScript = window.document.getElementById('facebook-jssdk');
fbScript.onload = fbScript.onreadystatechange = (function() {
logger.info('fbScript onLoad');
window.FB.init({
version: 'v2.1',
appId: '',
channelUrl: '/fbchannel.html',
status: false,
cookie: true,
xfbml: true,
logging: true,
oath: true
});
this.dispatch(constants.FACEBOOK_INIT_SUCCESS);
if(callback){
callback();
}
}.bind(this));
}
In my case it was an api version problem, as suggested by the error message.
Let the version loaded in the FB script tag match the one in your FB initialization script, by specifing the same when loading the sdk (in the hash), for instance for version 4.0:
<script src="https://connect.facebook.net/en_US/sdk.js#xfbml=1&version=v4.0"></script>
and in your script like:
window.fbAsyncInit = function() {
FB.init({
appId: XXX,
autoLogAppEvents: true,
xfbml: true,
version: 'v4.0' //<------------- same version
});
};