Facebook'un FB.init'i tamamlandığında nasıl tespit edilir


115

Eski JS SDK, FB.ensureInit adında bir işleve sahipti. Yeni SDK'nın böyle bir işlevi yok gibi görünüyor ... Tamamen başlatılana kadar api çağrıları yapmadığımdan nasıl emin olabilirim?

Bunu her sayfanın en üstüne ekliyorum:

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

Bu soruna çözümüm için bu bağlantıya bakın. facebook.stackoverflow.com/questions/12399428/…
Remi Grumeau

Yanıtlar:


138

04 Ocak 2012 güncellemesi

Görünüşe göre FB-bağımlı yöntemleri (örneğin FB.getAuthResponse()) daha FB.init()önce olduğu FB.init()gibi hemen sonra çağıramazsınız , şimdi asenkron gibi görünüyor. Kodunuzu FB.getLoginStatus()yanıt olarak sarmalamak, API'nin tam olarak hazır olup olmadığını tespit etme işini görür:

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

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

};  

veya fbEnsureInit()aşağıdan uygulama kullanılıyorsa :

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

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

};  

Orijinal Gönderi:

FB başlatıldığında sadece bir komut dosyası çalıştırmak istiyorsanız, içine bazı geri çağırma işlevi koyabilirsiniz 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'in tam olarak değiştirilmesini istiyorsanız, resmi bir değişiklik olmadığı için kendi başınıza bir şeyler yazmanız gerekir (büyük hata imo). İşte kullandığım şey:

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

Kullanımı:

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

2
Teşekkürler Serg .. sen bir efsanesin!
Pablo

3
FB.init çağrıldıktan hemen sonra bir Facebook API isteği çalıştıramıyorum - belki de kullandığım yöntem 'fql.query' olduğu için? Her iki durumda da, fbApiInit bayrağında uzun bir zaman aşımı ayarlamam gerekiyor.
Ian Hunter

Güncelleme için teşekkürler - Ben de aynı sorunu yaşıyordum ve güncellenmiş çözümünüz mükemmel çalıştı!
Terri Ann

@beanland, fql.query api çağrıları, kullanıcının oturum açmış olmasını gerektirir. Sorguyu responsegeri aldıktan sonra çalıştırdığınızdan emin misiniz FB.getLoginStatus(function(response){}? - "güncellenmiş cevap" ile "orijinal cevap" arasındaki farkı not edin.
tjmehta

@serg örnek için teşekkür ederim. fbAsyncInitwindow.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); };
Yüklemeden

38

Aslında Facebook, kimlik doğrulama olaylarına abone olmak için bir mekanizma sağlamıştır.

Sizin durumunuzda " status: true " kullanıyorsunuz , bu da FB nesnesinin Facebook'tan kullanıcının oturum açma durumunu isteyeceği anlamına gelir.

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 ()" çağırarak aynı isteği tekrar çalıştırıyorsunuz .

Bunun yerine kullanabilirsiniz FB.Event.subscribe abone olmak auth.statusChange veya auth.authResponseChange olay ÖNCE sen FB.init çağrı

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

Büyük olasılıkla, " status: false " kullanırken, FB.init'ten hemen sonra herhangi bir kodu çalıştırabilirsiniz, çünkü eşzamansız çağrı olmayacaktır.


NOT: Bu yöntemle tek uyarı, oturum açmadıysanız, olayın tetiklenmeyeceğidir. Varsayılan kullanıcı arayüzü durumunuzu kimliği doğrulanmamış gibi yapın ve mükemmel şekilde çalışır. Daha sonra olay işleyicisinin içinde bağlı olup olmadığını kontrol edebilirsiniz.
David C

Ayrıca, ön uç uygulamalar için, kullanıcı giriş yenilemeleri arasındaki durumunu, devam ettirme cookieiçin trueinit param nesnesi.
MK Safi

12

İşte kullanmanız durumunda bir çözüm ve 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
};

3
Onu seviyorum! Tek sorun, Facebook'un FB başlatma kodunuzu <body> açılış etiketinin hemen sonrasına eklemeniz gerektiğinde ısrar etmesi ve en iyi uygulama jQuery'yi <body> kapanış etiketinden önce yüklemeniz gerektiğini söylemesidir. Doh! Tavuk ve yumurta. "Siktir git Facebook" demeyi ve jQuery'den sonra FB'yi yüklemeyi baştan çıkarıyorum.
Ethan Brown

@EthanBrown Kabul ediyorum - sayfanızın muhtemelen jQuery'ye FB'ye ihtiyaç duyduğundan daha fazla ihtiyacı var, bu yüzden mantıklı. Yıllar önce sayfanın sonunda
jQuery'yi

version: 'v2.5'init json ekle diğer akıllıca işe yaramayacak .. en azından benim için olmadı. yardım için teşekkürler
Vikas Bansal

10

FB'nin başlatılıp başlatılmadığını kontrol etmenin başka bir yolu aşağıdaki kodu kullanmaktır:

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

Böylece sayfanızın hazır olayı içinde ns.FBInitialized'ı kontrol edebilir ve olayı setTimeOut kullanarak sonraki aşamaya erteleyebilirsiniz.


Bu gerçek bir şey! Teşekkürler!
Thiago Macedo

Bu basit olanı. Beğen
Faris Rayhan

5

Yukarıdaki çözümlerden bazıları işe yarasa da, FB başlatılıp kullanıma hazır hale gelir gelmez ateşlenecek 'hazır' bir yöntemi tanımlayan nihai çözümümüzü yayınlayacağımı düşündüm. FB hazır olmadan önce veya sonra aramak için güvenli olan diğer çözümlere göre avantaja sahiptir.

Şu şekilde kullanılabilir:

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

İşte kaynak dosya ('f52.fb' ad alanı içinde tanımlandığını unutmayın).

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

Genel bir işlev kullanarak setTimeout'u kullanmaktan kaçındım:

DÜZENLEME NOT: Aşağıdaki yardımcı komut dosyalarını güncelledim ve kullanımı daha kolay / daha basit bir sınıf oluşturdum; buradan kontrol edin ::: https://github.com/tjmehta/fbExec.js

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

fbEnsureInit, FB.init'ten sonra onu geri çağıracak

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

fbEnsureInitAndLoginStatus, FB.init'ten sonra ve FB.getLoginStatus'tan sonra onu geri çağıracak

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 örnek kullanımı:

(FB.login, FB başlatıldıktan sonra çalıştırılmalıdır)

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

fbEnsureInitAndLogin örnek kullanımı:

(FB.api'nin FB.init'ten sonra çalıştırılması ve FB kullanıcısının oturum açması gerekir.)

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

1
Yukarıdakinin aynısını daha kolay ve temiz bir şekilde yapan bu yardımcı sınıfı yazdım; buradan kontrol edin :: github.com/tjmehta/fbExec.js
tjmehta

4

Herhangi bir setTimeout veya setInterval kullanmak yerine, ertelenmiş nesnelere bağlı kalırım ( burada jQuery ile uygulama ). Kuyruğu doğru anda çözmek hala zordur, çünkü init'in geri aramaları yoktur, ancak sonucu olay aboneliğiyle birleştirmek (benden önce birinin işaret ettiği gibi) hile yapmalı ve yeterince yakın olmalıdır.

Sözde pasaj aşağıdaki gibi görünür:

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

İşte ne olay ne de zaman aşımı gerektirmeyen daha basit bir yöntem. Ancak jQuery gerektirir.

Kullan jQuery.holdReady() (dokümanlar)

Bu nedenle, jQuery betiğinizden hemen sonra ready olayını erteleyin.

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

Ardından, Facebook init işlevinizde bırakın:

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

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

Daha sonra ready olayını normal şekilde kullanabilirsiniz:

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

2

Etkinliğe abone olabilirsiniz:

yani)

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

2

Küçük ama ÖNEMLİ bildirimler:

  1. FB.getLoginStatusdaha sonra çağrılmalıdır FB.init, aksi takdirde olayı tetiklemeyecektir.

  2. kullanabilirsiniz FB.Event.subscribe('auth.statusChange', callback), ancak kullanıcı facebook'a giriş yapmadığında ateşlenmez.

İşte her iki işleve sahip çalışma örneği

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'i izler, böylece aşağıdaki gibi bir şeyle kendi API uygulamanızı çağırmadan önce bunu izleyebilirsiniz:

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

Bunun bir fark yarattığından emin değilim ama benim durumumda - çünkü kullanıcı arayüzünün hazır olduğundan emin olmak istedim - başlatmayı jQuery'nin hazır belgesiyle tamamladım (yukarıdaki son kısım):

  $(document).ready(FBreadyState);

Facebook'un all.js dosyasını yüklemek için async = true kullanmadığımı da unutmayın, ki bu benim durumumda kullanıcı arayüzüne giriş yapmaya ve özellikleri daha güvenilir bir şekilde sürmeye yardımcı oluyor gibi görünüyor.


1

Bazen fbAsyncInit çalışmaz. Nedenini bilmiyorum ve bu geçici çözümü kullanıyorum o zaman:

 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);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.