Rumah > Artikel > hujung hadapan web > Analisis mendalam fungsi panggil balik dalam JavaScript (segerak dan tak segerak)
Fungsi panggil balik ialah salah satu konsep yang perlu diketahui oleh setiap pengaturcara bahagian hadapan. Panggilan balik boleh digunakan dalam tatasusunan, fungsi pemasa, janji dan pengendalian acara. Artikel ini akan menerangkan konsep fungsi panggil balik dan membantu anda membezakan antara dua jenis panggil balik: segerak dan tak segerak.
Mula-mula tulis fungsi untuk menyambut orang.
Hanya buat fungsi name
yang menerima greet(name)
parameter. Fungsi ini sepatutnya mengembalikan mesej ucapan:
function greet(name) { return `Hello, ${name}!`; } greet('Cristina'); // => 'Hello, Cristina!'
Bagaimana jika anda memberi salam kepada ramai orang? Anda boleh menggunakan kaedah tatasusunan khas array.map()
untuk mencapai:
const persons = ['Cristina', 'Ana']; const messages = persons.map(greet); messages; // => ['Hello, Cristina!', 'Hello, Ana!']
persons.map(greet)
Dapatkan semua elemen tatasusunan persons
dan panggil fungsi greet()
dengan setiap elemen sebagai parameter panggilan : `greet('Cristina')
, greet('Ana')
.
Menariknya, kaedah persons.map(greet)
boleh menerima fungsi greet()
sebagai parameter. Dengan cara ini, greet()
menjadi fungsi panggil balik .
persons.map(greet)
ialah fungsi yang mengambil fungsi lain sebagai parameter, jadi ia dipanggil fungsi tertib lebih tinggi.
Fungsi panggil balik digunakan sebagai parameter fungsi tertib lebih tinggi dan fungsi tertib tinggi menjalankan operasi dengan memanggil fungsi panggil balik.
Perkara yang penting ialah fungsi peringkat tinggi bertanggungjawab untuk memanggil panggilan balik dan menyediakannya dengan parameter yang betul.
Dalam contoh sebelumnya, fungsi tertib tinggi persons.map(greet)
bertanggungjawab untuk memanggil fungsi greet()
dan masing-masing mengambil semua elemen dalam tatasusunan 'Cristina'
dan Ana '
sebagai parameter.
Ini menyediakan peraturan mudah untuk mengenal pasti panggilan balik. Jika anda mentakrifkan fungsi dan menyediakannya sebagai parameter kepada fungsi lain, maka ini mencipta panggilan balik.
Anda boleh menulis fungsi tertib tinggi anda sendiri menggunakan panggilan balik. Berikut ialah versi setara kaedah array.map()
:
function map(array, callback) { const mappedArray = []; for (const item of array) { mappedArray.push( callback(item) ); } return mappedArray; } function greet(name) { return `Hello, ${name}!`; } const persons = ['Cristina', 'Ana']; const messages = map(persons, greet);messages; // => ['Hello, Cristina!', 'Hello, Ana!']
map(array, callback)
ialah fungsi tertib lebih tinggi kerana ia memerlukan fungsi panggil balik sebagai argumen dan kemudian memanggil fungsi panggil balik itu di dalam badannya: callback(item)
.
Perhatikan bahawa fungsi biasa (ditakrifkan dengan kata kunci function
) atau fungsi anak panah (ditakrifkan dengan anak panah tebal =>
) juga boleh digunakan sebagai panggilan balik.
Terdapat dua cara untuk memanggil panggilan balik: segerak dan tak segerak panggil balik.
Panggil balik segerak "menyekat": fungsi tertib tinggi tidak meneruskan pelaksanaan sehingga fungsi panggil balik selesai.
Sebagai contoh, panggil fungsi map()
dan greet()
.
function map(array, callback) { console.log('map() starts'); const mappedArray = []; for (const item of array) { mappedArray.push(callback(item)) } console.log('map() completed'); return mappedArray; } function greet(name) { console.log('greet() called'); return `Hello, ${name}!`; } const persons = ['Cristina']; map(persons, greet); // logs 'map() starts' // logs 'greet() called' // logs 'map() completed'
di mana greet()
ialah panggilan balik segerak.
Langkah untuk menyegerakkan panggilan balik:
Pelaksanaan fungsi tertib lebih tinggi: 'map() starts'
Pelaksanaan fungsi panggilan balik: 'greet() called'
Akhirnya, fungsi tertib tinggi melengkapkan proses pelaksanaannya sendiri: 'map() completed'
, array.map(callback)
, array.forEach(callback)
, array.find(callback)
, array.filter(callback)
array.reduce(callback, init)
// Examples of synchronous callbacks on arrays const persons = ['Ana', 'Elena']; persons.forEach( function callback(name) { console.log(name); } ); // logs 'Ana' // logs 'Elena' const nameStartingA = persons.find( function callback(name) { return name[0].toLowerCase() === 'a'; } ); nameStartingA; // => 'Ana' const countStartingA = persons.reduce( function callback(count, name) { const startsA = name[0].toLowerCase() === 'a'; return startsA ? count + 1 : count; }, 0 ); countStartingA; // => 1Jenis rentetan
Kaedah juga boleh menerima panggilan balik yang dilaksanakan secara serentak: string.replace(callback)
// Examples of synchronous callbacks on strings const person = 'Cristina'; // Replace 'i' with '1' person.replace(/./g, function(char) { return char.toLowerCase() === 'i' ? '1' : char; } ); // => 'Cr1st1na'
ditangguhkan selama 2 saat: later()
console.log('setTimeout() starts'); setTimeout(function later() { console.log('later() called'); }, 2000); console.log('setTimeout() completed'); // logs 'setTimeout() starts' // logs 'setTimeout() completed' // logs 'later() called' (after 2 seconds)
ialah panggilan balik tak segerak kerana later()
memulakan dan menyelesaikan pelaksanaan, Tetapi setTimeout(later,2000)
dilaksanakan selepas 2 saat. later()
'setTimeout()starts'
'setTimeout() completed'
'later() called'
setTimeout(function later() { console.log('2 seconds have passed!'); }, 2000); // After 2 seconds logs '2 seconds have passed!' setInterval(function repeat() { console.log('Every 2 seconds'); }, 2000); // Each 2 seconds logs 'Every 2 seconds!'Pendengar acara DOM juga memanggil pengendali acara (subjenis fungsi panggil balik) secara tidak segerak:
const myButton = document.getElementById('myButton'); myButton.addEventListener('click', function handler() { console.log('Button clicked!'); }); // Logs 'Button clicked!' when the button is clicked
sebelum definisi fungsi akan mencipta fungsi tak segerak: async
async function fetchUserNames() { const resp = await fetch('https://api.github.com/users?per_page=5'); const users = await resp.json(); const names = users.map(({ login }) => login); console.log(names); }
fetchUserNames()
是异步的,因为它以 async
为前缀。函数 await fetch('https://api.github.com/users?per_page=5')
从 GitHub 上获取前5个用户 。然后从响应对象中提取 JSON 数据:await resp.json()
。
异步函数是 promise 之上的语法糖。当遇到表达式 await <promise>
(调用 fetch()
会返回一个promise)时,异步函数会暂停执行,直到 promise 被解决。
异步回调函数和异步函数是不同的两个术语。
异步回调函数由高阶函数以非阻塞方式执行。但是异步函数在等待 promise(await <promise>
)解析时会暂停执行。
但是你可以把异步函数用作异步回调!
让我们把异步函数 fetch UserNames()
设为异步回调,只需单击按钮即可调用:
const button = document.getElementById('fetchUsersButton'); button.addEventListener('click', fetchUserNames);
回调是一个可以作为参数传给另一个函数(高阶函数)执行的函数。
回调函数有两种:同步和异步。
同步回调是阻塞的。
异步回调是非阻塞的。
【相关推荐:javascript学习教程】
Atas ialah kandungan terperinci Analisis mendalam fungsi panggil balik dalam JavaScript (segerak dan tak segerak). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!