Buat panggilan balik khusus dalam JavaScript

322

Yang perlu saya lakukan adalah menjalankan fungsi callback ketika eksekusi fungsi saya saat ini berakhir.

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

Seorang konsumen untuk fungsi ini harus seperti ini:

object.LoadData(success);

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

Bagaimana saya menerapkan ini?

Amgad Fahmi
sumber
3
object.LoadData(success)panggilan harus setelah function success ditentukan. Jika tidak, Anda akan mendapatkan pesan kesalahan yang memberitahukan bahwa fungsi tersebut tidak didefinisikan.
J. Bruni

Jawaban:

574

Sebenarnya, kode Anda akan berfungsi sebagaimana mestinya, hanya menyatakan panggilan balik Anda sebagai argumen dan Anda dapat memanggilnya langsung menggunakan nama argumen.

Dasar

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

Itu akan memanggil doSomething, yang akan memanggil foo, yang akan mengingatkan "barang-barang masuk di sini".

Perhatikan bahwa sangat penting untuk meneruskan referensi fungsi ( foo), daripada memanggil fungsi dan meneruskan hasilnya ( foo()). Dalam pertanyaan Anda, Anda melakukannya dengan benar, tetapi itu hanya layak ditunjukkan karena itu adalah kesalahan umum.

Lebih banyak barang canggih

Terkadang Anda ingin memanggil panggilan balik sehingga melihat nilai spesifik untuk this. Anda dapat dengan mudah melakukannya dengan callfungsi JavaScript :

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`

Anda juga bisa memberikan argumen:

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`

Terkadang berguna untuk meneruskan argumen yang ingin Anda beri panggilan balik sebagai array, bukan secara individual. Anda dapat menggunakannya applyuntuk melakukan itu:

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`
TJ Crowder
sumber
Saya tahu ini akan berfungsi jika saya tidak memiliki parameter seperti contoh yang Anda tulis, tetapi ketika saya mencoba untuk melewati suatu fungsi dengan parameter, itu melempar pengecualian dan memberi tahu saya bahwa fungsinya tidak didefinisikan
Amgad Fahmi
@TiTaN: Aneh, tidak ada yang istimewa tentang melewatkan parameter ke dalam callback. Referensi callback yang Anda berikan ke fungsi Anda adalah referensi fungsi seperti yang lain, Anda dapat melakukan semua hal normal dengannya.
TJ Crowder
4
@semuanya yang menjawab: Saya pikir masalah TiTaN adalah bahwa dia tidak tahu cara meneruskan fungsi yang memerlukan argumen menjadi panggilan balik yang tidak lulus argumen apa pun. Pikirkan setTimeout(). Jawabannya adalah untuk menutup panggilan balik dalam penutupan:doSomething(function(){foo('this','should','work')})
slebetman
Seseorang mengarahkan TiTaN ke utas (lebih disukai di SO) yang membahas masalah di atas, pencarian-fu saya lemah hari ini.
slebetman
1
@Webwoman - Tergantung kasus penggunaan Anda. Anda bisa meneruskannya sebagai argumen, atau memasukkannya dalam beberapa jenis objek pengaturan / opsi, atau salah satu dari beberapa opsi lainnya.
TJ Crowder
78

Ini adalah praktik yang baik untuk memastikan callback adalah fungsi yang sebenarnya sebelum mencoba untuk mengeksekusinya:

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

  callback();
}
Donald A Nummer Jr
sumber
21
if(typeof callback == "function")akan memiliki hasil yang sama.
Reactgular
22
Ya, tetapi jika tidak ada panggilan balik, mengapa repot mengetiknya? Itulah intinya callback && ...
theonlygusti
61

2 sen saya. Sama tapi berbeda ...

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


    function dosomething(damsg, callback){
        alert(damsg);
        if(typeof callback == "function") 
        callback();
    }
</script>
K. Kilian Lindberg
sumber
7
Saya suka cuplikan ini, saya mencari ini
vimal1083
10
function loadData(callback) {

    //execute other requirement

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

loadData(function(){

   //execute callback

});
arun bahal
sumber
6
Silakan pertimbangkan untuk mengedit posting Anda untuk menambahkan lebih banyak penjelasan tentang apa yang kode Anda lakukan dan mengapa itu akan menyelesaikan masalah. Jawaban yang sebagian besar hanya berisi kode (bahkan jika itu berfungsi) biasanya tidak akan membantu OP untuk memahami masalah mereka. Namun dalam hal ini, ini adalah pertanyaan yang sangat lama dengan jawaban yang sangat terhormat yang sudah diposting, mungkin tidak ada gunanya saat Anda menjawab ini ketika ada pertanyaan baru yang bisa dilakukan dengan lebih banyak perhatian.
SuperBiasedMan
1
Saya suka jawaban ini untuk menunjukkan apa yang ingin dilihat orang.
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 !");
});

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

Hasilnya adalah:

hello world !
Eyad Farra
sumber
4

Jika Anda ingin menjalankan fungsi ketika sesuatu dilakukan. Salah satu solusi yang baik adalah mendengarkan acara. Sebagai contoh, saya akan mengimplementasikan a Dispatcher, sebuah DispatcherEventkelas dengan ES6, lalu:

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

Dispatcher:

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

Selamat coding!

p / s: Kode saya hilang menangani beberapa pengecualian kesalahan

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

Saat memanggil fungsi panggilan balik, kita dapat menggunakannya seperti di bawah ini:

consumingFunction(callbackFunctionName)

Contoh:

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

Ini adalah Codepend dengan contoh lengkap.

Eric Tan
sumber
1

Beberapa jawaban, meski benar mungkin agak sulit dipahami. Berikut adalah contoh istilah awam:

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

Panggilan balik berarti, "Jake" selalu ditambahkan ke pengguna sebelum menampilkan daftar pengguna dengan console.log.

Sumber (YouTube)

Dan Bray
sumber
0

Mencoba:

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

Fungsinya adalah kelas pertama dalam JavaScript ; Anda bisa membagikannya.

K Prime
sumber