JavaScript'te özel geri arama oluşturma


322

Tek yapmam gereken, geçerli işlev yürütme sona erdiğinde bir geri çağırma işlevi yürütmektir.

function LoadData() 
{
    alert('The data has been loaded');
    //Call my callback with parameters. For example,
    //callback(loadedData , currentObject);
}

Bu işlev için bir tüketici şöyle olmalıdır:

object.LoadData(success);

function success(loadedData , currentObject) 
{
  //Todo: some action here 
}

Bunu nasıl uygularım?


3
object.LoadData(success)çağrı tanımlandıktan sonra olmalıdır function success. Aksi takdirde, işlevin tanımlanmadığını bildiren bir hata alırsınız.
J. Bruni

Yanıtlar:


574

Aslında, kodunuz hemen hemen olduğu gibi çalışacaktır, sadece geri çağrınızı bir argüman olarak ilan edin ve doğrudan argüman adını kullanarak arayabilirsiniz.

Temeller

function doSomething(callback) {
    // ...

    // Call the callback
    callback('stuff', 'goes', 'here');
}

function foo(a, b, c) {
    // I'm the callback
    alert(a + " " + b + " " + c);
}

doSomething(foo);

Yani arayacak doSomethingarayacak olan foo, "şeyler buraya gelecektir" uyaracaktır hangi.

İşlevi çağırmak ve sonucunu ( ) iletmek yerine, reference ( foo) işlevini iletmenin çok önemli olduğunu unutmayın foo(). Sorunuzda, düzgün bir şekilde yapıyorsunuz, ancak dikkat çekmeye değer çünkü bu yaygın bir hatadır.

Daha gelişmiş şeyler

Bazen geri aramayı aramak istersiniz, böylece belirli bir değer görür this. Bunu JavaScript callişleviyle kolayca yapabilirsiniz :

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback) {
    // Call our callback, but using our own instance as the context
    callback.call(this);
}

function foo() {
    alert(this.name);
}

var t = new Thing('Joe');
t.doSomething(foo);  // Alerts "Joe" via `foo`

Ayrıca argümanları iletebilirsiniz:

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback, salutation) {
    // Call our callback, but using our own instance as the context
    callback.call(this, salutation);
}

function foo(salutation) {
    alert(salutation + " " + this.name);
}

var t = new Thing('Joe');
t.doSomething(foo, 'Hi');  // Alerts "Hi Joe" via `foo`

Bazen geri çağırma vermek istediğiniz bağımsız değişkenleri tek tek değil, bir dizi olarak iletmek yararlı olabilir. Bunu applyyapmak için kullanabilirsiniz :

function Thing(name) {
    this.name = name;
}
Thing.prototype.doSomething = function(callback) {
    // Call our callback, but using our own instance as the context
    callback.apply(this, ['Hi', 3, 2, 1]);
}

function foo(salutation, three, two, one) {
    alert(salutation + " " + this.name + " - " + three + " " + two + " " + one);
}

var t = new Thing('Joe');
t.doSomething(foo);  // Alerts "Hi Joe - 3 2 1" via `foo`

Yazdığınız örnek gibi herhangi bir parametreniz yoksa işe yarayacağını biliyorum ama parametrelerle bir işlevi geçmeye çalıştığımda bir istisna atıyor ve fonksiyonun tanımlanmadığını söylüyor
Amgad Fahmi

@TiTaN: Bu garip, parametreleri geri aramaya aktarmakla ilgili özel bir şey yok. İşlevinize ilettiğiniz geri arama referansı, diğer tüm işlevler gibi bir işlev referansıdır, bununla tüm normal şeyleri yapabilirsiniz.
TJ Crowder

4
@ Cevap veren herkes: Bence TiTaN'ın problemi, argüman gerektiren bir fonksiyonun herhangi bir argümanı geçmeyen bir geri çağrıya nasıl geçirileceğini bilmemesi. Düşün setTimeout(). Cevap geri aramayı bir kapanışa doSomething(function(){foo('this','should','work')})
sarmaktır

Birisi TiTaN'ı yukarıdaki sorunu tartışan bir iş parçacığına (tercihen SO'da) işaret ediyor, arama-fu'm bugün zayıf.
slebetman

1
@Webwoman - Kullanım durumunuza bağlıdır. Bir bağımsız değişken olarak iletebilir veya bir tür ayarlar / seçenekler nesnesine veya diğer birkaç seçenekten herhangi birine ekleyebilirsiniz.
TJ Crowder

77

Yürütmeyi denemeden önce geri aramanın gerçek bir işlev olduğundan emin olmak iyi bir uygulamadır:

if (callback && typeof(callback) === "function") {

  callback();
}

21
if(typeof callback == "function")aynı sonuca sahip olacak.
Reactgular

22
Evet, ancak geri arama yoksa, neden yazmayı rahatsız ediyorsunuz? İşte noktası callback && ...
theonlygusti

61

Benim 2 cent. Aynı ama farklı...

<script>
    dosomething("blaha", function(){
        alert("Yay just like jQuery callbacks!");
    });


    function dosomething(damsg, callback){
        alert(damsg);
        if(typeof callback == "function") 
        callback();
    }
</script>

7
Bu pasajı seviyorum, bunu arıyordum
vimal1083

10
function loadData(callback) {

    //execute other requirement

    if(callback && typeof callback == "function"){
        callback();
   }
}

loadData(function(){

   //execute callback

});

6
Kodunuzun ne yaptığı ve sorunun neden çözüleceği hakkında daha fazla açıklama eklemek için lütfen yayınınızı düzenleyin. Çoğunlukla sadece kod içeren bir yanıt (çalışıyor olsa bile) genellikle OP'nin sorunlarını anlamalarına yardımcı olmaz. Bununla birlikte, bu durumda, bu çok eski bir sorudur, daha önce dikkate alınmış cevaplar ile daha fazla dikkatle yapılabilecek daha yeni sorular olduğunda buna cevap verirken buna değmeyebilir.
SuperBiasedMan

1
Bu yanıtı, insanların görmek istedikleriyle ilgili str8 ileri gösterisini beğendim.
Aft3rL1f3

5
   function callback(e){
      return e;
   }
    var MyClass = {
       method: function(args, callback){
          console.log(args);
          if(typeof callback == "function")
          callback();
       }    
    }

==============================================

MyClass.method("hello",function(){
    console.log("world !");
});

==============================================

Sonuç:

hello world !

4

Bir şey yapıldığında bir işlevi yürütmek istiyorsanız. İyi bir çözüm, olayları dinlemek. Örneğin, a Dispatcher, DispatcherEventES6 ile bir sınıf uygulayacağım, sonra:

let Notification = new Dispatcher()
Notification.on('Load data success', loadSuccessCallback)

const loadSuccessCallback = (data) =>{
   ...
}
//trigger a event whenever you got data by
Notification.dispatch('Load data success')

Sevk görevlisi:

class Dispatcher{
  constructor(){
    this.events = {}
  }

  dispatch(eventName, data){
    const event = this.events[eventName]
    if(event){
      event.fire(data)
    }
  }

  //start listen event
  on(eventName, callback){
    let event = this.events[eventName]
    if(!event){
      event = new DispatcherEvent(eventName)
      this.events[eventName] = event
    }
    event.registerCallback(callback)
  }

  //stop listen event
  off(eventName, callback){
    const event = this.events[eventName]
    if(event){
      delete this.events[eventName]
    }
  }
}

DispatcherEvent:

class DispatcherEvent{
  constructor(eventName){
    this.eventName = eventName
    this.callbacks = []
  }

  registerCallback(callback){
    this.callbacks.push(callback)
  }

  fire(data){
    this.callbacks.forEach((callback=>{
      callback(data)
    }))
  }
}

Mutlu kodlama!

p / s: Kodum eksik bazı hata istisnalarını ele


1
function LoadData(callback) 
{
    alert('the data have been loaded');
    callback(loadedData, currentObject);
}

1

Geri arama işlevini çağırırken, aşağıdaki gibi kullanabiliriz:

consumingFunction(callbackFunctionName)

Misal:

// Callback function only know the action,
// but don't know what's the data.
function callbackFunction(unknown) {
  console.log(unknown);
}

// This is a consuming function.
function getInfo(thenCallback) {
  // When we define the function we only know the data but not
  // the action. The action will be deferred until excecuting.
  var info = 'I know now';
  if (typeof thenCallback === 'function') {
    thenCallback(info);    
  }
}

// Start.
getInfo(callbackFunction); // I know now

Bu, Codepend'in tam örneğidir.


1

Bazı cevaplar doğru olsa da anlaşılması biraz zor olabilir. Layman'ın terimleriyle ilgili bir örnek:

var users = ["Sam", "Ellie", "Bernie"];

function addUser(username, callback)
{
    setTimeout(function()
    {
        users.push(username);
        callback();
    }, 200);
}

function getUsers()
{
    setTimeout(function()
    {
        console.log(users);
    }, 100);
}

addUser("Jake", getUsers);

Geri arama, "Jake" olan kullanıcıların listesini görüntülemeden önce kullanıcılara her zaman eklendiği anlamına gelir. console.log .

Kaynak (YouTube)


0

Deneyin:

function LoadData (callback)
{
    // ... Process whatever data
    callback (loadedData, currentObject);
}

Fonksiyonlar JavaScript'te birinci sınıftır ; sadece etrafından geçebilirsin.

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.