development

페이스 북의 FB.init가 완료된 시점을 탐지하는 방법

big-blog 2020. 7. 24. 07:13
반응형

페이스 북의 FB.init가 완료된 시점을 탐지하는 방법


이전 JS SDK에는 FB.ensureInit라는 함수가있었습니다. 새로운 SDK에는 그런 기능이없는 것 같습니다 ... API가 완전히 시작될 때까지 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>

2012 년 1 월 4 일 업데이트

방금 (예 : FB-의존하는 방법을 호출 할 수 없습니다 것 같다 FB.getAuthResponse()직후) FB.init()전 등이 아니라, FB.init()지금 비동기 것 같다. 코드를 FB.getLoginStatus()응답 으로 감싸면 API가 완전히 준비된 시점을 감지하는 트릭을 수행하는 것 같습니다.

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");
});

실제로 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.init.subscribe사용하여 FB.init호출하기 전에 auth.statusChange 또는 auth.authResponseChange 이벤트 를 구독 할 수 있습니다.

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 직후에 모든 코드를 실행할 수 있습니다.


와 Facebook Asynchronous Lazy Loading 을 사용하는 경우의 해결책은 다음과 같습니다 .

// 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
};

FB가 초기화되었는지 확인하는 다른 방법은 다음 코드를 사용하는 것입니다.

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

따라서 페이지 준비 이벤트에서 ns.FBInitialized를 확인하고 setTimeOut을 사용하여 이벤트를 이후 단계로 연기 할 수 있습니다.


위의 솔루션 중 일부가 작동하는 동안 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
    };

})();

전역 함수를 사용하여 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.

      }
    });
  });
}

초기화 예제 사용법 :

FB가 초기화 된 후에 FB.login을 실행해야합니다.

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

fbEnsureInitAndLogin 사용법 예 :

FB.api는 FB.init 후에 실행해야하며 FB 사용자는 로그인해야합니다.

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

Instead of using any setTimeout or setInterval I would stick to deferred objects (implementation by jQuery here). It's still tricky to resolve queue in proper moment, because init don't have callbacks but combining result with event subscription (as someone pointed before me), should do the trick and be close enough.

Pseudo-snippet would look as follows:

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();
});

Here's a simpler method, that requires neither events or timeouts. It does require jQuery, however.

Use jQuery.holdReady() (docs)

So, immediately after your jQuery script, delay the ready event.

<!-- 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>

Then, in your Facebook init function, release it:

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

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

Then you can use the ready event as normal:

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

You can subscribe to the event:

ie)

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

Small but IMPORTANT notices:

  1. FB.getLoginStatus must be called after FB.init, otherwise it will not fire the event.

  2. you can use FB.Event.subscribe('auth.statusChange', callback), but it will not fire when user is not logged in facebook.

Here is the working example with both functions

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'));

The Facebook API watches for the FB._apiKey so you can watch for this before calling your own application of the API with something like:

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();
}; 

Not sure this makes a difference but in my case--because I wanted to be sure the UI was ready--I've wrapped the initialization with jQuery's document ready (last bit above):

  $(document).ready(FBreadyState);

Note too that I'm NOT using async = true to load Facebook's all.js, which in my case seems to be helping with signing into the UI and driving features more reliably.


Sometimes fbAsyncInit doesnt work. I dont know why and use this workaround then:

 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);

참고URL : https://stackoverflow.com/questions/3548493/how-to-detect-when-facebooks-fb-init-is-complete

반응형