Mendapatkan pemahaman yang lebih baik tentang fungsi-fungsi panggilan balik dalam JavaScript

163

Saya mengerti meneruskan fungsi ke fungsi lain sebagai panggilan balik dan menjalankannya, tapi saya tidak mengerti implementasi terbaik untuk melakukan itu. Saya mencari contoh yang sangat mendasar, seperti ini:

var myCallBackExample = {
    myFirstFunction : function( param1, param2, callback ) {
        // Do something with param1 and param2.
        if ( arguments.length == 3 ) {
            // Execute callback function.
            // What is the "best" way to do this?
        }
    },
    mySecondFunction : function() {
        myFirstFunction( false, true, function() {
            // When this anonymous function is called, execute it.
        });
    }
};

Di myFirstFunction, jika saya mengembalikan panggilan balik baru (), maka berfungsi dan menjalankan fungsi anonim, tetapi itu sepertinya bukan pendekatan yang tepat untuk saya.


sumber
Benar dalam arti apa? Biasanya panggilan balik digunakan untuk penangan acara - terutama panggilan Ajax, yang tidak sinkron - pada dasarnya hal-hal di mana Anda tidak tahu kapan (atau jika) resposne akan datang.
cletus
2
omong-omong argumennya adalah array seperti tetapi bukan array, jadi Anda tidak bisa melakukan argument.length tetapi Anda bisa mengonversinya menjadi array menggunakan metode slice ...
paul
1
@ paul, meskipun Anda benar argumentsbukan array, Anda masih bisa merujuk panjangnya sebagai arguments.length- cobalah. Properti ini mengacu pada jumlah argumen yang benar-benar diteruskan, dan belum tentu jumlah parameter dalam tanda tangan fungsi.
hotshot309

Jawaban:

132

Anda bisa mengatakannya

callback();

Bergantian Anda dapat menggunakan callmetode ini jika Anda ingin menyesuaikan nilai thisdalam panggilan balik.

callback.call( newValueForThis);

Di dalam fungsinya thisakan menjadi apa pun newValueForThisitu.

krosenvold
sumber
91

Anda harus memeriksa apakah panggilan balik itu ada, dan merupakan fungsi yang dapat dieksekusi:

if (callback && typeof(callback) === "function") {
    // execute the callback, passing parameters as necessary
    callback();
}

Banyak perpustakaan (jQuery, dojo, dll.) Menggunakan pola yang sama untuk fungsi asinkronnya, serta node.js untuk semua fungsi async (nodejs biasanya lewat errordan datake panggil balik). Melihat ke kode sumber mereka akan membantu!

arunjitsingh
sumber
Mengapa Anda melemparkan callbackke string dan kemudian memeriksa tipenya? Apakah ini akan meningkatkan kinerja? Ini seperti memeriksa jenis, memeriksa apakah boolean yang dikonversi mengembalikan nilai true dan kemudian memeriksa jenisnya lagi dan mengujinya terhadap string ... Bisakah Anda menjelaskan mengapa?
headacheCoder
Saya ingin tahu mengapa Anda memerlukan pernyataan panggilan balik pertama ... apakah ini untuk memeriksa nol atau tidak ditentukan? Tidak akan typeof(callback)mencapai itu untuk Anda? typeof(null) === "Object",typeof("undefined") === "undefined"
PJH
1
Hubung singkat DAN. Jika panggilan balik tidak ada, jangan repot-repot menghitung tipenya. Padahal kamu benar. Tidak diperlukan dengan typeof (), tetapi saya akan melakukan jsperf dan melihat apakah hubungan pendek itu sepadan.
arunjitsingh
@ headacheCoder - callbacktidak dilemparkan ke string, tipenya sedang diperiksa untuk melihat apakah itu suatu fungsi, sebelum dipanggil. Kode mungkin diterima callbacksebagai argumen, dan tidak pasti bahwa argumen tersebut adalah tipe yang dapat dipanggil - atau mungkin argumen tersebut dari berbagai jenis dalam upaya untuk menyediakan bentuk polimorfisme di mana kode dapat bereaksi secara berbeda terhadap typeofargumen yang berbeda .
LeeGee
34

Ada 3 kemungkinan utama untuk menjalankan suatu fungsi:

var callback = function(x, y) {
    // "this" may be different depending how you call the function
    alert(this);
};
  1. panggilan balik (argument_1, argument_2);
  2. callback.call (some_object, argument_1, argument_2);
  3. callback.apply (some_object, [argumen_1, argument_2]);

Metode yang Anda pilih tergantung apakah:

  1. Anda memiliki argumen yang disimpan dalam Array atau sebagai variabel yang berbeda.
  2. Anda ingin memanggil fungsi itu dalam konteks beberapa objek. Dalam hal ini, menggunakan kata kunci "ini" dalam panggilan balik itu akan merujuk objek yang dilewatkan sebagai argumen dalam panggilan () atau berlaku (). Jika Anda tidak ingin meneruskan konteks objek, gunakan null atau undefined. Dalam kasus terakhir objek global akan digunakan untuk "ini".

Documents untuk Function.call , Function.apply

Ionuț G. Stan
sumber
6

Panggilan balik adalah tentang sinyal dan "baru" adalah tentang membuat instance objek.

Dalam hal ini akan lebih tepat untuk mengeksekusi "callback ();" daripada "return callback baru ()" karena Anda toh tidak melakukan apa pun dengan nilai pengembalian.

(Dan argumen.length == 3 tes benar-benar kikuk, fwiw, lebih baik untuk memeriksa bahwa param callback ada dan merupakan fungsi.)

annakata
sumber
6

implementasi yang tepat adalah:

if( callback ) callback();

ini membuat parameter callback opsional ..

faeb187
sumber
Bagaimana jika argumen panggilan balik bukan suatu fungsi?
Yaki Klein
2

Kamu bisa memakai:

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

Contoh di bawah ini sedikit lebih komprehensif:

function mySandwich(param1, param2, callback) {
  alert('Started eating my sandwich.\n\nIt has: ' + param1 + ', ' + param2);
  var sandwich = {
      toppings: [param1, param2]
    },
    madeCorrectly = (typeof(param1) === "string" && typeof(param2) === "string") ? true : false;
  if (callback && typeof(callback) === "function") {
    callback.apply(sandwich, [madeCorrectly]);
  }
}

mySandwich('ham', 'cheese', function(correct) {
  if (correct) {
    alert("Finished eating my " + this.toppings[0] + " and " + this.toppings[1] + " sandwich.");
  } else {
    alert("Gross!  Why would I eat a " + this.toppings[0] + " and " + this.toppings[1] + " sandwich?");
  }
});

Hasan A Yousef
sumber
1

Berikut ini adalah contoh dasar yang menjelaskan callback()fungsi dalam JavaScript:

var x = 0;

function testCallBack(param1, param2, callback) {
  alert('param1= ' + param1 + ', param2= ' + param2 + ' X=' + x);
  if (callback && typeof(callback) === "function") {
    x += 1;
    alert("Calla Back x= " + x);
    x += 1;
    callback();
  }
}

testCallBack('ham', 'cheese', function() {
  alert("Function X= " + x);
});

JSFiddle

BERGUIGA Mohamed Amine
sumber
1

function checkCallback(cb) {
  if (cb || cb != '') {
    if (typeof window[cb] === 'undefined') alert('Callback function not found.');
    else window[cb].call(this, Arg1, Arg2);
  }
}

Aamir Afridi
sumber