FacebookのFB.initが完了したことを検出する方法


115

古いJS SDKには、FB.ensureInitという関数がありました。新しいSDKにはそのような機能がないようです...完全に開始されるまでAPI呼び出しを行わないようにするにはどうすればよいですか?

これを各ページの上部に含めます。

<div id="fb-root"></div>
<script>
  window.fbAsyncInit = function() {
    FB.init({
      appId  : '<?php echo $conf['fb']['appid']; ?>',
      status : true, // check login status
      cookie : true, // enable cookies to allow the server to access the session
      xfbml  : true  // parse XFBML
    });
    FB.Canvas.setAutoResize();
  };

  (function() {
    var e = document.createElement('script');
    e.src = document.location.protocol + '//connect.facebook.net/en_US/all.js';
    e.async = true;
    document.getElementById('fb-root').appendChild(e);
  }());
</script>

この問題に対する私の解決策については、このリンクを参照してください。 facebook.stackoverflow.com/questions/12399428/...
レミGrumeau

回答:


138

2012年1月4日の更新

今は非同期のように見えるので、以前のようにすぐにFB依存のメソッド(たとえばFB.getAuthResponse())を呼び出すことはできないようです。コードを応答にラップすることで、APIが完全に準備ができたことを検出するトリックを行うようです。FB.init()FB.init()FB.getLoginStatus()

window.fbAsyncInit = function() {
    FB.init({
        //...
    });

    FB.getLoginStatus(function(response){
        runFbInitCriticalCode(); 
    });

};  

またはfbEnsureInit()以下の実装を使用する場合:

window.fbAsyncInit = function() {
    FB.init({
        //...
    });

    FB.getLoginStatus(function(response){
        fbApiInit = true;
    });

};  

元の投稿:

FBが初期化されたときにスクリプトを実行したい場合は、内部にいくつかのコールバック関数を配置できますfbAsyncInit

  window.fbAsyncInit = function() {
    FB.init({
      appId  : '<?php echo $conf['fb']['appid']; ?>',
      status : true, // check login status
      cookie : true, // enable cookies to allow the server to access the session
      xfbml  : true  // parse XFBML
    });
    FB.Canvas.setAutoResize();

    runFbInitCriticalCode(); //function that contains FB init critical code
  };

FB.ensureInitの正確な置き換えが必要な場合は、公式の置き換えがないため、自分で何かを記述する必要があります(大きな間違いimo)。これが私が使うものです:

  window.fbAsyncInit = function() {
    FB.init({
      appId  : '<?php echo $conf['fb']['appid']; ?>',
      status : true, // check login status
      cookie : true, // enable cookies to allow the server to access the session
      xfbml  : true  // parse XFBML
    });
    FB.Canvas.setAutoResize();

    fbApiInit = true; //init flag
  };

  function fbEnsureInit(callback) {
        if(!window.fbApiInit) {
            setTimeout(function() {fbEnsureInit(callback);}, 50);
        } else {
            if(callback) {
                callback();
            }
        }
    }

使用法:

fbEnsureInit(function() {
    console.log("this will be run once FB is initialized");
});

2
ありがとうSerg ..あなたは伝説です!
パブロ

3
FB.initが呼び出された直後にFacebook APIリクエストを実行できません-おそらく、私が使用しているメソッドが 'fql.query'であるためでしょうか?どちらの方法でも、fbApiInitフラグに長いタイムアウトを設定する必要があります。
Ian Hunter

アップデートをありがとう-私は同じ問題を抱えていて、あなたのアップデートされたソリューションは完璧に機能しました!
Terri Ann

@ beanland、fql.query api呼び出しでは、ユーザーがログインしている必要があります。responseから戻った後にクエリを実行していますFB.getLoginStatus(function(response){}か?-上記の「更新された回答」と「元の回答」の違いに注意してください。
tjmehta

@sergは例をありがとう。私は、関数の内部に遅延を入れていたfbAsyncInitことが、ロード後に呼び出されるためにwindow.fbAsyncInit = function() { FB.init({ appId : '*************', channelUrl : 'http://www.mydomain.com', status : true, // check login status cookie : true, // enable cookies to allow the server to access the session oauth : true, // enable OAuth 2.0 xfbml : true // parse XFBML }); setTimeout(function() { myfunction(function (callback) {}, '', '', '' ); }, 1200); };
TQ

38

実際、Facebookはすでに認証イベントをサブスクライブするメカニズムを提供しています。

あなたの場合、「status:true」を使用しています。これは、FBオブジェクトがFacebookにユーザーのログインステータスを要求することを意味します。

FB.init({
    appId  : '<?php echo $conf['fb']['appid']; ?>',
    status : true, // check login status
    cookie : true, // enable cookies to allow the server to access the session
    xfbml  : true  // parse XFBML
});

「FB.getLoginStatus()」を呼び出すことで、同じリクエストを再度実行しています。

代わりに、使用することができFB.Event.subscribeをを購読するauth.statusChangeまたはauth.authResponseChangeイベント前にあなたがFB.initを呼び出します

FB.Event.subscribe('auth.statusChange', function(response) {
    if(response.status == 'connected') {
        runFbInitCriticalCode();
    }
});

FB.init({
    appId  : '<?php echo $conf['fb']['appid']; ?>',
    status : true, // check login status
    cookie : true, // enable cookies to allow the server to access the session
    xfbml  : true  // parse XFBML
});

ほとんどの場合、「status:false」を使用すると、非同期呼び出しがないため、FB.initの直後に任意のコードを実行できます。


注:この方法の唯一の注意点は、ログインしていない場合、イベントがトリガーされないことです。認証されていないかのようにデフォルトのUI状態を作成するだけで、完全に機能します。次に、イベントハンドラー内でconnectedまたはnot_authorizedを確認できます。
デビッドC

また、フロントエンドアプリの場合、更新間でユーザーのログインステータスを維持cookieするにtrueは、init paramオブジェクトでに設定します。
MKサフィ2017年

12

これがあなたが使う場合の解決策です およびFacebook非同期遅延読み込み:

// listen to an Event
$(document).bind('fbInit',function(){
    console.log('fbInit complete; FB Object is Available');
});

// FB Async
window.fbAsyncInit = function() {
    FB.init({appId: 'app_id', 
         status: true, 
         cookie: true,
         oauth:true,
         xfbml: true});

    $(document).trigger('fbInit'); // trigger event
};

3
大好きです!唯一の問題は、Facebookが<body>開始タグの直後にFB initコードを含める必要があると主張していることです。ベストプラクティスでは、<body>終了タグの前にjQueryをロードする必要があります。どー!鶏肉と卵。私は「Facebookを台無しにして」と言い、jQueryの後にFBをロードしたくなります。
イーサンブラウン

@EthanBrown同意します-あなたのページはおそらくFBを必要とするよりもjQueryを必要とするので、それは理にかなっています。数年前のページの最後でjQueryをロードするのを
やめました

version: 'v2.5'init jsonを追加しないと、うまくいきません。少なくとも、私にとってはうまくいきませんでした。助けてくれてありがとう
Vikas Bansal

10

FBが初期化されているかどうかを確認する別の方法は、次のコードを使用することです。

ns.FBInitialized = function () {
    return typeof (FB) != 'undefined' && window.fbAsyncInit.hasRun;
};

したがって、ページ準備完了イベントでns.FBInitializedを確認し、setTimeOutを使用してイベントを後のフェーズに延期できます。


これは本物です!ありがとう!
チアゴマセド2015年

これは簡単なものです。いいね
ファリスレイ

5

上記の解決策のいくつかは機能しますが、最終的な解決策を投稿すると思いました。これは、FBが初期化されて準備ができたらすぐに起動する「準備完了」メソッドを定義します。FBの準備ができる前でも後でも呼び出すことが安全であるという点で、他のソリューションよりも優れています。

次のように使用できます。

f52.fb.ready(function() {
    // safe to use FB here
});

これがソースファイルです( 'f52.fb'名前空間内で定義されていることに注意してください)。

if (typeof(f52) === 'undefined') { f52 = {}; }
f52.fb = (function () {

    var fbAppId = f52.inputs.base.fbAppId,
        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: fbAppId,
            xfbml: true,
            version: 'v2.0'
        });

        FB.getLoginStatus(function(response){
            fbApiInit = true;
            notifyQ();
        });
    };

    return {
        /**
         * Fires callback when FB is initialized and ready for api calls.
         */
        'ready': ready
    };

})();

4

グローバル関数を使用してsetTimeoutを使用しないようにしました。

編集注:以下のヘルパースクリプトを更新し、使いやすく/簡単なクラスを作成しました。ここで確認してください::: https://github.com/tjmehta/fbExec.js

window.fbAsyncInit = function() {
    FB.init({
        //...
    });
    window.fbApiInit = true; //init flag
    if(window.thisFunctionIsCalledAfterFbInit)
        window.thisFunctionIsCalledAfterFbInit();
};

fbEnsureInitは、FB.initの後にコールバックを呼び出します

function fbEnsureInit(callback){
  if(!window.fbApiInit) {
    window.thisFunctionIsCalledAfterFbInit = callback; //find this in index.html
  }
  else{
    callback();
  }
}

fbEnsureInitAndLoginStatusは、FB.initの後とFB.getLoginStatusの後でコールバックを呼び出します

function fbEnsureInitAndLoginStatus(callback){
  runAfterFbInit(function(){
    FB.getLoginStatus(function(response){
      if (response.status === 'connected') {
        // the user is logged in and has authenticated your
        // app, and response.authResponse supplies
        // the user's ID, a valid access token, a signed
        // request, and the time the access token
        // and signed request each expire
        callback();

      } else if (response.status === 'not_authorized') {
        // the user is logged in to Facebook,
        // but has not authenticated your app

      } else {
        // the user isn't logged in to Facebook.

      }
    });
  });
}

fbEnsureInitの使用例:

(FBが初期化された後にFB.loginを実行する必要があります)

fbEnsureInit(function(){
    FB.login(
       //..enter code here
    );
});

fbEnsureInitAndLoginの使用例:

(FB.apiは、FB.initおよびFBユーザーがログインした後に実行する必要があります。)

fbEnsureInitAndLoginStatus(function(){
    FB.api(
       //..enter code here
    );
});

1
このヘルパークラスは、上記と同じように簡単かつクリーンな方法で実行します。ここをチェックしてください:: github.com/tjmehta/fbExec.js
tjmehta

4

setTimeoutまたはsetIntervalを使用する代わりに、据え置きオブジェクトに固執します(ここでの jQueryによる実装))。initにはコールバックがありませんが、結果をイベントサブスクリプションと組み合わせると(誰かが私の前に指摘したように)、トリックを実行し、十分に近いはずです。

擬似スニペットは次のようになります。

FB.Event.subscribe('auth.statusChange', function(response) {
   if (response.authResponse) {
       // user has auth'd your app and is logged into Facebook
   } else {
       // user has not auth'd your app, or is not logged into Facebook
   }
   DeferredObject.resolve();
});

4

これは、イベントもタイムアウトも必要としない、より単純な方法です。ただし、jQueryは必要です。

使用jQuery.holdReady() (ドキュメント)

したがって、jQueryスクリプトの直後に、readyイベントを遅延させます。

<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
    $.holdReady( true ); // don't fire ready until told (ie when FB loaded)
</script>

次に、Facebookのinit関数で、それを解放します。

window.fbAsyncInit = function() {
    FB.init({
        appId: '11111111111111',
        cookie: true,
        xfbml: false,
        version: 'v2.4'
    });

    // release the ready event to execute
    $.holdReady( false );
};

その後、通常どおりreadyイベントを使用できます。

$(document).ready( myApp.init );

2

イベントに登録できます:

すなわち)

FB.Event.subscribe('auth.login', function(response) {
  FB.api('/me', function(response) {
    alert(response.name);
  });
});

2

小さいが重要な通知:

  1. FB.getLoginStatusの後FB.initに呼び出す必要があります。そうしないと、イベントは発生しません。

  2. を使用できますがFB.Event.subscribe('auth.statusChange', callback)、ユーザーがFacebookにログインしていない場合は起動しません。

これは両方の機能を使った作業例です

window.fbAsyncInit = function() {
    FB.Event.subscribe('auth.statusChange', function(response) {
        console.log( "FB.Event.subscribe auth.statusChange" );
        console.log( response );
    });

    FB.init({
        appId   : "YOUR APP KEY HERE",
        cookie  : true,  // enable cookies to allow the server to access
                // the session
        xfbml   : true,  // parse social plugins on this page
        version : 'v2.1', // use version 2.1
        status  : true
    });

    FB.getLoginStatus(function(response){
        console.log( "FB.getLoginStatus" );
        console.log( response );
    });

};

// Load the SDK asynchronously
(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'));

1

Facebook APIはFB._apiKeyを監視するため、次のようなAPIの独自のアプリケーションを呼び出す前にこれを監視できます。

window.fbAsyncInit = function() {
  FB.init({
    //...your init object
  });
  function myUseOfFB(){
    //...your FB API calls
  };
  function FBreadyState(){
    if(FB._apiKey) return myUseOfFB();
    setTimeout(FBreadyState, 100); // adjust time as-desired
  };
  FBreadyState();
}; 

これが違いをもたらすかどうかはわかりませんが、私の場合-UIが準備できていることを確認したかったため、jQueryのドキュメントの準備ができた状態で初期化をラップしました(上記の最後のビット):

  $(document).ready(FBreadyState);

Facebookのall.jsを読み込むためにasync = trueを使用していないことにも注意してください。私の場合は、UIへのサインインと機能のより確実な駆動に役立つようです。


1

fbAsyncInitが機能しない場合があります。理由がわからないので、この回避策を使用します。

 var interval = window.setInterval(function(){
    if(typeof FB != 'undefined'){
        FB.init({
            appId      : 'your ID',
            cookie     : true,  // enable cookies to allow the server to access// the session
            xfbml      : true,  // parse social plugins on this page
            version    : 'v2.3' // use version 2.3
        });

        FB.getLoginStatus(function(response) {
            statusChangeCallback(response);
        });
        clearInterval(interval);
    }
},100);
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.