Masih ingat tentang closures?
const variabelGlobal = 'global';
const fnLuar = () => {
const variabelLokal = 'lokal';
const fnDalam = (paramDalam) => {
return 'halo ' + variabelLokal + ' ' + paramDalam;
};
return fnDalam; // tidak diinvoke
};
const fnKembalian = fnLuar(); // return fnDalam
console.log(fnKembalian('ini untuk dalam')); // invoke fnDalam
console.log(fnKembalian('ini dijagain')); // invoke fnDalam
Sebuah fungsi di dalam javascript bisa mengembalikan sebuah fungsi lainnya?
Dalam dunia pemrograman, ada 2 cara proses:
Sync = eksekusi program yang akan menunggu proses sebelumnya selesai, sebelum prosesnya dijalankan (blocking)
Async = eksekusi program yang dapat berjalan tanpa menunggu proses sebelumnya selesai (non-blocking)
Analoginya adalah order makanan: Drive-through vs Order restoran
(function fnSync() {
console.log('1');
console.log('2');
console.log('3');
})();
(function fnAsync() {
console.log('A');
console.log('B');
// setTimeout adalah fungsi, di dalamnya menerima
// sebuah parameter fungsi
setTimeout(function() {
console.log('Process C');
}, 1000);
console.log('D');
})();
Apakah outputnya?
Sebuah fungsi yang dijadikan sebuah argumen pada fungsi lainnya
Misalnya saya punya beberapa pekerjaan yang harus dilakukan:
Kita coba lihat urutan kerjaannya yah:
Sedikit Catatan
Mari kita coba lihat contoh kodenya - tanpa callback
function main() {
telponDenganSiDia();
// apabila tanpa callback
// maka ini akan menunggu 30 s.d. 1 jam
// baru bisa mengerjakan pekerjaan selanjutnya
mengerjakanTantangan();
cuciBaju();
}
Mari kita coba lihat contoh kodenya - dengan callback
function main() {
telponDenganSiDia(function siDiaTelponBalik(diaSudahSiap) {
bucinan(diaSudahSiap);
});
mengerjakanTantangan();
cuciBaju();
}
function fungsiKesatu() {
console.log('satu');
}
function fungsiKedua() {
console.log('dua');
}
fungsiKesatu();
fungsiKedua();
Di kode ini, fungsiKesatu akan dijalankan duluan sebelum fungsiKedua
Mari kita pikirkan suatu hal
function fungsiKesatu() {
// simulasi delay async sebagai analogi aksi yang lama
setTimeout(() => {
console.log('satu');
}, 1000);
}
function fungsiKedua() {
console.log('dua');
}
// secara logika yang kita tahu
// seharusnya ini akan berjalan dahulu
fungsiKesatu();
// baru yang ini bukan?
fungsiKedua();
Mari coba kita lihat outputnya !
Misalnya kita ingin membuat sebuah fungsi yang menerima array of number yang bisa melakukan pencarian angka ganjil saja
function pemilahAngka(deretAngka) {
let hasil = [];
for (let counter = 0; counter < deretAngka.length; counter++) {
// modulus / modulo (%) adalah angka sisa pembagian
if (deretAngka[counter] % 2 === 1) {
hasil.push(deretAngka[counter]);
}
}
return hasil;
}
const deretAngka = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
console.log(pemilahAngka(deretAngka));
Sekarang kita ingin membuat fungsi pemilahAngka bisa melakukan pemilahan berdasarkan fungsi yang diberikan (callback)
Sekarang mari kita melihat kode dengan callbacknya
Klik di sini(Kode dituliskan di stackblitz karena sudah melebihi area yang bisa dilihat di slide)
// karena fungsiKesatu yang harus menunggu fungsiKedua
// maka callbacknya akan dimasukkan ke sini
function fungsiKesatu(fnCallback) {
setTimeout(() => {
// ketika timeout sudah selesai console log ini akan berjalan
console.log('satu');
// baru setelah itu fnCallback di-invoke
fnCallback();
}, 1000);
}
function fungsiKedua() {
console.log('dua');
}
fungsiKesatu(fungsiKedua);
Mirip dengan Looping, Callback juga bisa di-nestedkan
(Kode dituliskan di stackblitz karena sudah melebihi area yang bisa dilihat di slide)
Penggunaan berlebihan nested callback bisa menghasilkan sesuatu yang "menyenangkan"
Umumnya dikenal dengan nama Callback Hell atau Pyramid of Doom