Mengapa kita membutuhkan "fungsi panggilan balik"?

16

Saya sedang membaca buku programming in Lua. Dikatakan begitu

Penutupan menyediakan alat yang berharga dalam banyak konteks. Seperti yang telah kita lihat, mereka berguna sebagai argumen untuk fungsi tingkat tinggi seperti sort. Penutupan juga bermanfaat untuk fungsi yang membangun fungsi lain, seperti contoh Penghitung baru kami; mekanisme ini memungkinkan program Lua untuk menggabungkan teknik pemrograman canggih dari dunia fungsional. Penutupan juga berguna untuk fungsi panggilan balik. Contoh khas di sini terjadi ketika Anda membuat tombol di toolkit GUI konvensional. Setiap tombol memiliki fungsi callback untuk dipanggil ketika pengguna menekan tombol; Anda ingin tombol yang berbeda melakukan hal yang sedikit berbeda ketika ditekan. Misalnya, kalkulator digital membutuhkan sepuluh tombol serupa, satu untuk setiap digit. Anda dapat membuat masing-masing dengan fungsi seperti ini:

function digitButton (digit)
  return Button{label = tostring(digit),
                action = function ()
                  add_to_display(digit)
                  end}
end

Tampaknya jika saya memanggil digitButton, ia akan mengembalikan action(ini akan membuat penutupan), jadi, saya dapat mengakses yang digitditeruskan ke digitButton.

Pertanyaan saya adalah:

Why we need call back functions? what situations can I apply this to?


Penulis berkata:

Dalam contoh ini, kami menganggap bahwa Button adalah fungsi toolkit yang membuat tombol baru; label adalah label tombol; dan action adalah penutupan callback untuk dipanggil ketika tombol ditekan. Callback dapat dipanggil lama setelah digitButton melakukan tugasnya dan setelah digit variabel lokal keluar dari ruang lingkup, tetapi masih dapat mengakses variabel ini.

menurut penulis, saya pikir contoh serupa adalah seperti ini:

function Button(t)
  -- maybe you should set the button here
  return t.action -- so that you can call this later
end

function add_to_display(digit)
  print ("Display the button label: " .. tostring(digit))
end

function digitButton(digit)
  return Button{label = tostring(digit),
                action = function ()
                           add_to_display(digit)
                           end}
end

click_action = digitButton(10)
click_action()

jadi, the callback can be called a long time after digitButton did its task and after the local variable digit went out of scope.

Lucas Li
sumber

Jawaban:

45

Guy 1 ke Guy 2: hai Bung aku ingin melakukan sesuatu ketika pengguna mengklik di sana, menelepon saya kembali ketika itu terjadi, oke?

Guy 2 memanggil balik Guy 1 ketika pengguna mengklik di sini.

Florian Margaine
sumber
1
Saya sangat suka lelucon panggilan balik ini :-P
Lucas Li
6
Apakah hanya saya? Saya tidak mengerti bagaimana ini menjelaskan mengapa kita membutuhkan fungsi panggilan balik.
phant0m
2
Ini lebih seperti kata Guy 1 kepada Guy 2 "ketika waktunya tepat melakukan ini". Guy 2 menjalani harinya dan ketika waktunya tepat melakukan itu. Jika Anda menjadikan Guy 1 sebagai penelepon Guy 2, maka ini tidak benar karena Guy 2 tidak memanggil kembali Guy 1, ia memanggil hal yang harus dilakukan. Bahkan jika Guy 1 adalah penelepon Guy 2 Anda akan memiliki loop keras di tangan Anda dalam skenario ini. Jika Anda ingin Guy 1 menjadi panggilan balik maka ini tidak benar karena panggilan balik tidak tahu siapa Guy 2 dan tentu saja tidak memintanya untuk menelepon.
rism
Ini penjelasan yang mengerikan.
Di dalam
21

Tidak, itu tidak akan pernah mengembalikan aksinya. Tombol akan menjalankannya ketika pengguna mengkliknya. Dan itu jawabannya. Anda memerlukan fungsi panggil balik ketika Anda ingin mendefinisikan tindakan yang harus terjadi di komponen lain sebagai reaksi terhadap peristiwa yang tidak Anda kontrol (loop peristiwa, yang merupakan bagian dari sistem, akan menjalankan metode tombol yang pada gilirannya akan mengeksekusi tindakan).

Jan Hudec
sumber
Aku tidak setuju denganmu Saya telah mengedit posting saya dan menambahkan beberapa kode. Saya masih berpikir bahwa tindakan tersebut tidak dijalankan secara instan.
Lucas Li
2
Tim, Anda benar - tetapi demikian juga Jan. "Tombol akan menjalankannya ketika pengguna mengkliknya", tidak secara instan.
AlexanderBrevig
@AlexanderBrevig ya, saya masih berpikir balasan Jan sangat berguna bagi saya. Ini membuat saya tahu apa itu panggilan balik dan mengapa kita perlu menelepon kembali.
Lucas Li
Callback hanyalah nama kotor yang ditambahkan seseorang ke fungsi kedua yang berfungsi saat yang pertama dipecat dan mungkin berdasarkan kriteria. Panggil fungsi Anda dengan baik () dan tidak akan ada perbedaan. Panggilan balik seperti Verifikasi, verifikasi adalah urutan pesan, biasanya dua, dan panggilan balik adalah fungsi yang penting, biasanya dua. Jika Anda merantai lebih dari 3 panggilan balik, selamat, Anda suka melakukan hal-hal yang sulit.
m3nda
16

Saya pikir contoh yang lebih baik untuk penggunaan callback adalah dalam fungsi asinkron. Saya tidak dapat berbicara untuk Lua, tetapi dalam JavaScript, salah satu tindakan asinkron yang paling umum adalah menghubungi server melalui AJAX.

Panggilan AJAX tidak sinkron, artinya jika Anda melakukan sesuatu seperti ini:

var ajax = ajaxCall();
if(ajax == true) {
  // Do something
}

isi ifblok tidak akan berjalan dengan andal, dan ketika itu terjadi, itu hanya karena ajaxCall()fungsi terjadi untuk menyelesaikan sebelum eksekusi mencapai ifpernyataan.

Namun, panggilan balik menghilangkan masalah ini, dengan memastikan panggilan asinkron selesai sebelum memanggil fungsi yang diperlukan. Jadi, kode Anda akan berubah menjadi seperti ini:

function ajaxCallback(response) {   
  if(response == true) {
    // Do something   
  }
}

ajaxCall(ajaxCallback);

Tujuannya adalah untuk memungkinkan Anda melakukan hal-hal seperti mengumpulkan data, tanpa mengganggu hal-hal lain, seperti menggambar antarmuka. Jika pengumpulan data adalah sinkron, maka antarmuka akan menjadi tidak responsif saat aplikasi menunggu untuk mendapatkan data. Antarmuka yang tidak responsif sangat buruk untuk pengalaman pengguna, karena sebagian besar pengguna akan berpikir aplikasi telah "macet" dan akan mencoba untuk menghentikan proses.

Untuk melihat ini dalam tindakan, Anda hanya perlu melihat situs web apa pun yang melakukan segala jenis pembaruan tanpa memuat ulang seluruh halaman. Twitter, LinkedIn, dan situs StackExchange adalah contoh yang bagus. "Gulir tak berujung" Twitter dari umpan, dan pemberitahuan SE (untuk pemberitahuan pengguna, dan pemberitahuan bahwa suatu pertanyaan memiliki aktivitas baru), diberdayakan oleh panggilan tak sinkron. Ketika Anda melihat pemintal di suatu tempat, itu berarti bagian itu telah membuat panggilan tidak sinkron, dan sedang menunggu panggilan itu selesai, tetapi Anda dapat berinteraksi dengan hal-hal lain pada antarmuka (dan bahkan membuat panggilan tidak sinkron lainnya). Setelah panggilan itu selesai, ia akan bereaksi dan memperbarui antarmuka yang sesuai.

Shauna
sumber
12

Anda mengajukan pertanyaan

Mengapa kita membutuhkan "fungsi panggil kembali"?

Saya akan mencoba menjawabnya secara ringkas dan jelas (jika saya gagal, silakan merujuk ke tautan wiki di bagian bawah jawaban ini).

Callback digunakan untuk menunda implementasi spesifik dari sesuatu ke saat terakhir yang memungkinkan.

Contoh tombol adalah ilustrasi yang bagus untuk ini. Katakanlah Anda ingin memiliki tombol di aplikasi Anda yang mencetak halaman ke printer, kita dapat membayangkan dunia di mana Anda harus kode seluruh PrinterButtonkelas baru untuk melakukan ini.

Untungnya, kita memiliki gagasan tentang callback (pewarisan dan penggunaan pola template juga semacam semantik callback) sehingga kita tidak perlu melakukan itu.

Alih-alih menerapkan kembali setiap aspek tombol, yang kami lakukan adalah menambah implementasi tombol. The Buttonmemiliki konsep melakukan sesuatu ketika itu ditekan. Kami hanya mengatakan apa itu sesuatu.

Mekanisme menyuntikkan perilaku ke dalam kerangka kerja disebut callback.

Contoh:

Mari menyuntikkan beberapa perilaku ke tombol HTML:

<button onclick="print()">Print page through a callback to the print() method</button>

Dalam contoh ini, onclickmenunjuk ke panggilan balik, yang untuk contoh ini adalah print()metode.


http://en.wikipedia.org/wiki/Callback_(computer_programming)

AlexanderBrevig
sumber
Terima kasih, setelah membaca ilustrasi Anda, saya pergi untuk membaca wiki yang contohnya hanya panggilan balik yang sinkron.
Lucas Li
beri tahu fungsi jawabannya setiap kali ada masalah dan Anda harus mendengarkan masalahnya; mengajarkan fungsi untuk memecahkan masalah yang harus ditangani sendiri.
Joe
8

Mengapa kita perlu fungsi panggilan balik? situasi apa saya bisa menerapkan ini?

Fungsi panggilan balik sangat berguna dalam pemrograman berbasis acara. Mereka memungkinkan Anda untuk mengatur program Anda sedemikian rupa sehingga acara akan memicu kode yang benar. Ini sangat umum dalam program dengan GUI di mana pengguna dapat mengklik elemen apa pun di UI (seperti tombol atau item menu) dan kode yang sesuai akan dijalankan.

FrustratedWithFormsDesigner
sumber
1
+ Itulah gunanya callback, tetapi saya benci harus menulisnya :-)
Mike Dunlavey
Ketika saya masih mahasiswa baru, guru saya mengajari kami cara memprogram di MFC, tetapi dia tidak pernah memberi tahu kami apa itu panggilan balik :-(
Lucas Li
2

Apa yang terjadi tanpa panggilan balik:

Guy 1: Oke, saya menunggu hal itu terjadi. (peluit, twiddles thumbs)

Guy 2: Sialan! Mengapa Guy 1 tidak menunjukkan barang kepada saya? Saya ingin melihat hal-hal terjadi !! Dimana barang-barangku? Bagaimana orang melakukan sesuatu di sekitar sini?

Jim
sumber
1

Pertama, istilah panggilan balik mengacu pada penutupan yang sedang digunakan untuk sesuatu.

Misalnya, anggap Anda membuat fungsi penutupan dan hanya menyimpannya dalam variabel. Itu bukan panggilan balik, karena itu tidak digunakan untuk apa pun.

Tapi, misalkan Anda membuat penutupan dan menyimpannya di suatu tempat yang akan dipanggil ketika sesuatu terjadi. Sekarang disebut panggilan balik.

Biasanya, callback dibuat oleh bagian program yang berbeda dari bagian yang memanggilnya. Jadi mudah untuk membayangkan bahwa beberapa bagian dari program "memanggil kembali" bagian lain.

Sederhananya, panggilan balik memungkinkan satu bagian dari program untuk memberitahu bagian lain untuk melakukan sesuatu (apa saja) ketika sesuatu terjadi.

Sedangkan untuk variabel yang tetap hidup karena digunakan dalam penutupan, itu fitur yang sama sekali berbeda yang disebut upvalues ​​(alias "memperpanjang masa pakai variabel lokal" di antara mereka yang tidak berbicara Lua). Dan itu cukup berguna juga.

Jonathan Graef
sumber
ya, Extending the lifetime of local variablesini juga untuk mengatakan istilah upvalue.
Lucas Li
Hmm menarik. Istilah peningkatan nilai tampaknya khusus untuk Lua, meskipun pencarian Google cepat menunjukkan bahwa kadang-kadang digunakan untuk menggambarkan bahasa lain. Saya akan menambahkannya ke jawaban saya.
Jonathan Graef
1

Telepon balik sudah ada sejak awal Fortran, setidaknya. Misalnya, jika Anda memiliki pemecah ODE (persamaan diferensial biasa), seperti pemecah Runge-Kutta, mungkin akan terlihat seperti ini:

subroutine rungekutta(neq, t, tend, y, deriv)
  integer neq             ! number of differential equations
  double precision t      ! initial time
  double precision tend   ! final time
  double precision y(neq) ! state vector
  ! deriv is the callback function to evaluate the state derivative
  ...
  deriv(neq, t, y, yprime) ! call deriv to get the state derivative
  ...
  deriv(neq, t, y, yprime) ! call it several times
  ...
end subroutine

Ini memungkinkan penelepon untuk menyesuaikan perilaku subrutin dengan melewatinya fungsi tujuan khusus untuk dipanggil bila perlu. Ini memungkinkan ODE solver digunakan untuk mensimulasikan berbagai sistem.

Mike Dunlavey
sumber
1

Menemukan ini dan ingin memberikan jawaban yang lebih terkini ...

Fungsi panggilan balik memungkinkan kita melakukan sesuatu dengan data di lain waktu, memungkinkan kode lain dijalankan, alih-alih menunggu. Kode asinkron memungkinkan kita untuk mengeksekusi apa saja nanti . Contoh fungsi callback yang paling mudah dibaca yang saya temui adalah Janji dalam JavaScript. Dalam contoh di bawah ini setiap kali Anda melihat fungsi (hasil) atau (hasil baru) atau (hasil akhir) ... ini adalah fungsi panggilan balik. Kode di dalam kurung keriting mereka dijalankan setelah data kembali dari server. Hanya pada titik ini akan masuk akal untuk menjalankan fungsi-fungsi ini karena sekarang data yang mereka butuhkan tersedia.

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

kodenya diambil dari ... https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

Semoga ini bisa membantu seseorang. Inilah yang membantu saya memahami panggilan balik :)

NRV
sumber
1
ini tampaknya tidak menawarkan sesuatu yang substansial atas poin yang dibuat dan dijelaskan dalam 9 jawaban sebelumnya
nyamuk
1
Mungkin untuk Anda, tetapi inilah yang benar-benar membuat panggilan balik jelas bagi saya, jadi saya pikir saya akan membagikannya. IMO keterbacaan contoh adalah apa yang membuatnya berharga. Saya yakin kita bisa sepakat bahwa kode mudah dibaca, terutama untuk pemula.
NRV
-2

Saya tidak tahu lua tetapi secara umum metode panggilan balik seperti multithreading. Sebagai contoh dalam pemrograman pengembangan aplikasi mobile sebagian besar aplikasi berfungsi seperti mengirim permintaan ke server dan bermain dengan UI dengan data datang sebagai respons dari server. Ketika pengguna mengirim permintaan ke server, akan butuh waktu untuk mendapatkan respons dari server tetapi untuk UX UI terbaik tidak boleh macet.

Karena itu kami menggunakan banyak utas untuk melakukan operasi paralel. Ketika kami mendapat respons dari server, kami perlu memperbarui UI. kita harus memberi tahu dari utas itu untuk memperbarui. dari dunia fungsional. Jenis panggilan fungsi ini disebut metode panggilan balik. Ketika Anda memanggil metode ini, controle harus kembali ke utas utama. Misalnya metode panggilan balik adalah blok di objektif-C.

AMohan
sumber
ya, apa yang Anda katakan konsisten dengan pemahaman saya setelah membaca buku.
Lucas Li
2
Metode panggilan balik tidak seperti multithreading. Metode panggilan balik hanyalah pointer fungsi (delegasi). Thread adalah tentang pengalihan / pemanfaatan konteks CPU. Kontras yang sangat sederhana adalah bahwa threading adalah tentang pengoptimalan CPU untuk UX sedangkan callback adalah tentang pengalihan memori untuk polimorfisme. Hanya karena utas mungkin mengeksekusi callback tidak berarti threading dan callback serupa. Thread juga mengeksekusi metode statis pada kelas statis tetapi jenis threading dan statis tidak serupa.
rism