Dalam pemrograman imperatif tipikal , Anda menulis urutan instruksi dan mereka dieksekusi satu demi satu, dengan aliran kontrol eksplisit. Sebagai contoh:
if [ -f file1 ]; then # If file1 exists ...
cp file1 file2 # ... create file2 as a copy of a file1
fi
dll.
Seperti yang dapat dilihat dari contoh, dalam pemrograman imperatif Anda mengikuti alur eksekusi dengan cukup mudah, selalu bekerja dengan cara Anda dari setiap baris kode tertentu untuk menentukan konteks eksekusi, mengetahui bahwa setiap instruksi yang Anda berikan akan dieksekusi sebagai hasil dari perintah mereka. lokasi di aliran (atau lokasi situs panggilan mereka, jika Anda menulis fungsi).
Bagaimana panggilan balik mengubah alur
Saat Anda menggunakan panggilan balik, alih-alih menempatkan penggunaan serangkaian instruksi "secara geografis", Anda menjelaskan kapan harus dipanggil. Contoh umum dalam lingkungan pemrograman lain adalah kasus seperti "unduh sumber ini, dan ketika unduhan selesai, panggil panggilan balik ini". Bash tidak memiliki konstruk panggilan balik generik dari jenis ini, tetapi ia memiliki panggilan balik, untuk penanganan kesalahan dan beberapa situasi lainnya; misalnya (kita harus terlebih dahulu memahami substitusi perintah dan mode keluar Bash untuk memahami contoh itu):
#!/bin/bash
scripttmp=$(mktemp -d) # Create a temporary directory (these will usually be created under /tmp or /var/tmp/)
cleanup() { # Declare a cleanup function
rm -rf "${scripttmp}" # ... which deletes the temporary directory we just created
}
trap cleanup EXIT # Ask Bash to call cleanup on exit
Jika Anda ingin mencoba ini sendiri, simpan di atas dalam file, katakan cleanUpOnExit.sh
, buat itu dapat dieksekusi dan jalankan:
chmod 755 cleanUpOnExit.sh
./cleanUpOnExit.sh
Kode saya di sini tidak pernah secara eksplisit memanggil cleanup
fungsi; ia memberi tahu Bash kapan harus memanggilnya, menggunakan trap cleanup EXIT
, yaitu "Bash sayang, tolong jalankan cleanup
perintah ketika Anda keluar" (dan cleanup
kebetulan merupakan fungsi yang saya definisikan sebelumnya, tapi itu bisa apa saja yang dipahami Bash). Bash mendukung ini untuk semua sinyal non-fatal, keluar, kegagalan perintah, dan debugging umum (Anda dapat menentukan panggilan balik yang dijalankan sebelum setiap perintah). Callback di sini adalah cleanup
fungsi, yang "dipanggil kembali" oleh Bash tepat sebelum shell keluar.
Anda dapat menggunakan kemampuan Bash untuk mengevaluasi parameter shell sebagai perintah, untuk membangun kerangka kerja berorientasi-panggilan balik; itu agak di luar ruang lingkup jawaban ini, dan mungkin akan menyebabkan lebih banyak kebingungan dengan menyarankan bahwa fungsi lewat di sekitar selalu melibatkan panggilan balik. Lihat Bash: meneruskan fungsi sebagai parameter untuk beberapa contoh fungsionalitas yang mendasarinya. Idenya di sini, seperti halnya callback penanganan event, adalah bahwa fungsi dapat mengambil data sebagai parameter, tetapi juga fungsi lainnya - ini memungkinkan penelepon untuk memberikan perilaku serta data. Contoh sederhana dari pendekatan ini bisa terlihat
#!/bin/bash
doonall() {
command="$1"
shift
for arg; do
"${command}" "${arg}"
done
}
backup() {
mkdir -p ~/backup
cp "$1" ~/backup
}
doonall backup "$@"
(Saya tahu ini agak tidak berguna karena cp
dapat menangani banyak file, hanya untuk ilustrasi.)
Di sini kita membuat fungsi,, doonall
yang mengambil perintah lain, diberikan sebagai parameter, dan menerapkannya ke seluruh parameternya; maka kita menggunakannya untuk memanggil backup
fungsi pada semua parameter yang diberikan ke skrip. Hasilnya adalah skrip yang menyalin semua argumennya, satu per satu, ke direktori cadangan.
Pendekatan semacam ini memungkinkan fungsi ditulis dengan tanggung jawab tunggal: doonall
tanggung jawab adalah menjalankan sesuatu pada semua argumennya, satu per satu; backup
Tanggung jawabnya adalah membuat salinan argumennya (satu-satunya) di direktori cadangan. Keduanya doonall
dan backup
dapat digunakan dalam konteks lain, yang memungkinkan lebih banyak penggunaan kembali kode, pengujian yang lebih baik, dll.
Dalam hal ini, callback adalah backup
fungsi, yang kita beri tahu doonall
untuk “menelepon kembali” pada masing-masing argumen lainnya - kami menyediakan doonall
perilaku (argumen pertama) serta data (argumen yang tersisa).
(Perhatikan bahwa dalam jenis use-case yang ditunjukkan pada contoh kedua, saya tidak akan menggunakan istilah "callback" sendiri, tapi itu mungkin kebiasaan yang dihasilkan dari bahasa yang saya gunakan. Saya menganggap ini sebagai fungsi lewat atau lambda di sekitar , daripada mendaftarkan panggilan balik dalam sistem berorientasi peristiwa.)