Apa itu panggilan balik ditangguhkan?

15

Saya memahami ide panggilan balik, di mana saya meneruskan fungsi ke fungsi lain dan fungsi itu kemudian menggunakan fungsi yang disediakan sesuka hati.

Saya kesulitan memahami panggilan balik yang ditunda, bahkan setelah googling.

Bisakah seseorang memberikan penjelasan sederhana? Saya memprogram di Ruby, tetapi juga tahu C / C ++ sedikit, tetapi yang terpenting saya adalah programmer bahasa assembly yang berpengalaman. Jadi saya bertanya-tanya apakah ini sedikit seperti tumpukan alamat panggilan balik yang muncul? Saya berharap untuk belajar jquery atau node.js dan panggilan balik yang ditangguhkan ini tampaknya integral untuk keduanya. Saya mengerti prinsip dasar threading (meskipun objek mutex membuat kepala saya sakit;)

sepuluh kali
sumber
Apakah maksud Anda objek jQuery Deferred? Apakah ini tentang sesuatu yang spesifik untuk Node.js?
bfavaretto
1
Tidak, maksud saya secara umum. Meskipun saya ingin belajar jquery dan mungkin node.js, saya merasa bahwa saya perlu memahami apa panggilan balik yang ditunda sebenarnya adalah yang pertama. Saya membaca artikel Wikipedia tentang callback, tetapi saya tidak bisa mendapatkan pemahaman tentang callback yang ditunda, yang tampaknya intrinsik dengan paradigma operasi asinkron yang akan terlibat dalam bahasa-bahasa yang menggunakannya.
1
Saya benar-benar meminta ide konseptual panggilan balik ditangguhkan sebagai lawan dari implementasinya - maaf jika saya tidak menjelaskannya. Saya memberikan contoh-contoh bahasa lebih banyak untuk menjelaskan gagasan yang saya coba perjelas dan juga latar belakang pemrograman saya sehingga orang-orang akan tahu bagaimana cara menjawabnya. Terima kasih banyak atas jawabannya sejauh ini - saya akan sampai di sana!
tentimes
Ok saya pikir saya sudah mendapatkannya sekarang, terima kasih untuk kalian semua! Saya tidak tahu bagaimana cara menjawabnya. Cameron menjelaskan konsep paling sederhana dan itulah yang benar-benar saya cari, tetapi yang lain juga ikut berdiskusi dan menambah pengetahuan saya. Saya tidak yakin cara apa untuk menerima jawabannya karena saya masih baru dalam hal ini;)
tentimes

Jawaban:

4

Atas permintaan, berikut adalah komentar yang disajikan sebagai jawaban:


Saya tidak yakin Anda benar-benar memahami fakta bahwa fungsi di JS adalah objek kelas satu, dan karenanya dapat disimpan sampai dibutuhkan, melewati waktu mereka dibuat.

Misalnya, Anda ingin menulis ke file, lalu cetak pesan log; jadi Anda memanggil fungsi "write ()" (atau apa pun) dan meneruskannya fungsi yang menampilkan pesan log (ini adalah fungsi callback yang ditangguhkan). "write ()" secara internal menyimpan referensi ke fungsi yang diberikan, mulai menulis ke file, dan mengatur panggilan baliknya sendiri untuk mengetahui kapan penulisan selesai. Kemudian kembali sebelum penulisan dilakukan; ketika itu, panggilan balik internal entah bagaimana disebut (ini adalah pekerjaan kerangka kerja yang mendasarinya - dalam kasus node.js, itu dilakukan dengan loop peristiwa), yang kemudian memanggil panggilan balik Anda yang mencetak pesan log.

Bagian "ditangguhkan" berarti bahwa fungsi panggilan balik Anda tidak langsung dipanggil; panggilan itu ditangguhkan sampai waktu yang tepat. Dalam kasus fungsi asinkron seperti banyak yang ada di node.js, panggilan balik yang diberikan umumnya dipanggil saat operasi selesai (atau terjadi kesalahan).

Sebagian besar barang async di node.js, tetapi di browser dengan misal jQuery, sebagian besar barang sebenarnya sinkron (kecuali, jelas, untuk permintaan AJAX). Karena fungsi kelas satu sangat berguna dalam JavaScript (terutama karena dukungan penutupan yang hebat), panggilan balik juga digunakan di mana-mana di browser, tetapi mereka tidak "ditangguhkan" untuk operasi sinkron (kecuali sejauh mereka tidak dipanggil segera oleh Anda, tetapi nanti dengan fungsi yang Anda panggil).

Fakta bahwa sistem yang mendasarinya adalah event-driven adalah ortogonal untuk penggunaan panggilan balik ditangguhkan; Anda dapat membayangkan versi node.js (sangat lambat) yang memulai utas untuk setiap operasi, dan kemudian memanggil panggilan balik yang diberikan saat utas selesai bekerja, tanpa menggunakan acara sama sekali. Tentu saja, ini adalah model yang mengerikan, tetapi menggambarkan maksud saya :-)

Cameron
sumber
8

Cara panggilan balik ditunda berfungsi adalah setiap kali Anda menambahkan panggilan balik ke dalamnya, panggilan balik itu didorong ke sebuah array. Kemudian, ketika metode .resolve()atau .resolveWith()dipanggil pada objek yang ditangguhkan, semua .done()panggilan balik dalam array dieksekusi secara berurutan.

Sekarang kita bisa melihat apa Objek Ditangguhkan itu. Ambil cuplikan di bawah ini sebagai contoh.

var deferred = $.Deferred();
var promise = deferred.promise();

Apa yang kita miliki sekarang adalah objek yang ditangguhkan, dan objek janji objek yang ditangguhkan. Objek ditangguhkan memiliki semua metode yang sama sebagai objek janji, namun objek janji hanya memiliki metode .done(), .fail()dan .always()yang digunakan untuk menambahkan callback ke objek ditangguhkan untuk setiap masing-masing event. Objek yang ditangguhkan di sisi lain memiliki beberapa metode lain, yang paling penting .resolve()dan .reject(). Ketika metode ini dipanggil pada objek yang ditangguhkan, semua panggilan balik dipanggil. .resolve()memecat .done()dan memanggil .always()kembali sementara .reject()metode panggilan .fail()dan panggilan .always()balik.

Umumnya objek yang ditangguhkan disimpan tersembunyi dalam ruang lingkup pribadi, dan objek janji dikembalikan dari fungsi sehingga callback dapat ditempatkan di atasnya. Objek yang ditangguhkan akan diselesaikan nanti, seperti setelah permintaan ajax selesai atau setelah gambar dimuat, setelah setTimeout, dll. Juga penting untuk menyadari bahwa objek yang ditangguhkan hanya dapat diselesaikan satu kali. Jika sudah diselesaikan, panggilan balik itu akan segera dipanggil.

Inilah contoh lain, yang saya gunakan:

function loadImage(url) {
    var def = $.Deferred(),
        img = new Image();
    $(img).on("load error",function(e){
        if (e.type === "error") {
            def.reject(url);
        }
        else {
            def.resolve(url);
        }
    });
    img.src = url;
    // return the promise object so that callbacks can
    // be defined on the deferred object.
    return def.promise();
}
loadImage("foobar.jpg").done(function(){
    alert("The image is loaded!");
}).fail(function(){
    alert("The image failed to load!");
}).always(function(){
    alert("This is always called!");
});

Untuk informasi lebih lanjut tentang $.Deferred()metode jQuery dan objek yang ditangguhkan, kunjungi http://api.jquery.com/category/deferred-object/

pengguna400654
sumber
Ini mungkin akan sangat berharga setelah saya memahami konsep panggilan balik yang ditunda. Maaf, tapi saya masih tidak mengerti konsep apa panggilan balik yang ditunda. Saya lebih mencari ide konseptual di baliknya. Semacam ide Mihia. Setelah saya bisa mendapatkan kepala saya itu maka mungkin saya bisa mengerti js.
tentimes
3

Saya tidak yakin, tetapi saya percaya panggilan balik yang tertunda mengacu pada panggilan balik yang tidak sinkron, jadi Anda akan lebih beruntung di google untuk itu.

Penjelasan terbaik yang saya temukan adalah di http://www.nodebeginner.org

Hai, mungkinExpensiveFunction (), tolong lakukan tugas Anda, tapi saya, utas Node.js tunggal, tidak akan menunggu di sini sampai Anda selesai, saya akan terus menjalankan baris kode di bawah Anda, jadi tolong ambil fungsi callback ini () di sini dan menyebutnya ketika Anda selesai melakukan hal-hal mahal Anda? Terima kasih!"

Dalam contoh ini, mungkinExpensiveFunction adalah fungsi non-blocking (atau async). Ini berarti bahwa itu tidak dieksekusi segera, tetapi ditempatkan dalam suatu peristiwa yang disebut loop. Thread node.js akan melanjutkan eksekusi, tetapi pada titik tertentu, ia akan memutuskan untuk mengeksekusi sesuatu dari loop peristiwa. Ketika mencapai mungkinExpensiveFunction, ia memanggilnya, dan ketika mungkinExpensiveFunction menyelesaikan eksekusi, ia memanggil callback (ditangguhkan) yang dilewatkan sebagai parameter untuk itu.

Sebagai contoh dari mungkinExpensiveFunction, Anda dapat mengambil fs.readFile

mihai
sumber
Terima kasih. Tapi, bagaimana fungsi mahal akan melakukan hal-hal itu jika sudah kembali dan Anda kembali ke utas eksekusi? Saya tidak mengerti. Apakah Anda mengatakan fungsi tetap ada setelah beberapa saat?
Diedit jawabannya, mungkin lebih jelas sekarang.
Sangat membantu. Tapi ... apakah saya harus memroses array callback tersimpan ini? Yang saya maksud adalah, apa yang memproses daftar ini. Apakah (misalnya) bahwa js mengangkat callback ini di latar belakang dengan Anda tidak melakukan apa-apa, atau apakah suatu peristiwa menyebabkan node.js atau sesuatu untuk memanggil callback tertentu. Maaf, saya mendapatkan sekitar 70% dari apa yang Anda katakan tetapi saya hanya sedikit tersesat di sisanya :)
tentimes
@tentimes - "apa yang memproses daftar ini" objek $ .Deferred () sedang memproses daftar. Ketika Anda menelepon .resolve()atau .reject()pada objek yang ditangguhkan asli, daftar panggilan balik dipanggil.
user400654
2
@tentimes: Dari apa yang Anda katakan, saya tidak yakin Anda benar-benar memahami fakta bahwa fungsi di JS adalah objek kelas satu, dan karena itu dapat disimpan sampai dibutuhkan, melewati waktu mereka dibuat. Misalnya katakan Anda ingin menulis ke file, lalu cetak pesan log; jadi Anda memanggil fungsi "tulis" (atau apa pun) dan berikan fungsi yang menampilkan pesan log. "write ()" secara internal menyimpan referensi ke fungsi yang diberikan, mulai menulis ke file, dan mengatur panggilan baliknya sendiri untuk mengetahui kapan penulisan selesai. Kemudian kembali sebelum penulisan dilakukan; ketika itu, fungsi Anda dipanggil.
Cameron
3

JavaScript adalah utas tunggal, jadi Anda tidak dapat berpikir dalam hal utas untuk memahami ini. Berikut adalah contoh dari callback biasa dan tidak sinkron menggunakan jQuery:

var regularCallback = function(evt) {
    alert("I'm a callback!")
}
var asyncCallback = function(data) {
    alert("I only run when an async operation finishes!")
}

// Bind the regular callback to a button's click event
$('#mybutton').on('click', regularCallback);

// Start an ajax request to the server. The request is asynchronous, so code
// below this line will execute immediately. The callback function
// will only be called when the request is complete.
$.get("http://google.com", asyncCallback);
bfavaretto
sumber
Sekarang ini membawa saya ke suatu tempat, terima kasih. Jadi asinkron adalah sebagai respons terhadap suatu peristiwa yang telah saya setup dengan ajax - yang hanya membatalkannya dan jika peristiwa itu terjadi, panggilan balik saya akan dipanggil? Saya pikir saya mengerti. Akankah node.js / jquery melakukan sesuatu yang mirip dengan jquery usnig objek yang ditangguhkan dan sistem yang rumit berinteraksi dengan mereka untuk benar-benar hanya melakukan hal yang sama tetapi menggunakan metode?
tentimes
1
@tentimes, Tepat! Panggilan balik biasanya dijalankan sebagai respons terhadap peristiwa (tetapi karena "panggilan balik" bukan merupakan konstruksi bahasa js, terkadang istilah tersebut digunakan dalam konteks lain). Benda yang ditangguhkan (janji) yang Anda lihat dalam jawaban Kevin pada dasarnya adalah gula sintaksis. Mereka mendapatkan "diselesaikan" atau "ditolak" ketika beberapa peristiwa (asinkron) dipicu, kemudian mereka memanggil panggilan balik yang sesuai ("selesai" atau "gagal", lalu "selalu"). Menggunakannya di jQuery dapat membuat kode lebih mudah dibaca, dan memungkinkan untuk beberapa trik tambahan (seperti dengan mudah menambahkan callback kedua setelah mem-request permintaan ajax, misalnya).
bfavaretto
Keduanya adalah panggilan balik yang tidak sinkron
Raynos
1

Callback ditangguhkan (alias Janji ) memungkinkan Anda untuk menulis kode asinkron berurutan, tanpa rasa sakit dan spageti callback:

$.when( doAjax(), doAnotherAjax() ).then( haveFunWithMoreAjax ).then( animateStuff );

'kapan' memungkinkan Anda menunggu fungsi kembali secara paralel, dan thendapat dirantai secara berurutan.

satu catatan: jQuery ditangguhkan ! = Janji / A , sintaks mereka sedikit berbeda.

Ada artikel bagus tentang topik: satu di IEBlog dan lainnya di beberapa blog acak , buku, dan pertanyaan tentang stackoverflow yang populer

c69
sumber
1
uhh .. ternyata - OP menanyakan hal yang sedikit berbeda .. yah, semoga jawaban ini akan membantu orang lain, suatu hari nanti, mungkin.
c69