Home >Web Front-end >JS Tutorial >In-depth analysis of callback functions in JavaScript (synchronous and asynchronous)
Callback function is one of the concepts that every front-end programmer should know. Callbacks can be used in arrays, timer functions, promises, and event handling. This article will explain the concept of callback functions and help you distinguish between two types of callbacks: synchronous and asynchronous.
First write a function to greet people.
Just create a function greet(name)
that accepts the name
parameter. This function should return the greeting message:
function greet(name) { return `Hello, ${name}!`; } greet('Cristina'); // => 'Hello, Cristina!'
What if you greet many people? You can use the special array method array.map()
to achieve:
const persons = ['Cristina', 'Ana']; const messages = persons.map(greet); messages; // => ['Hello, Cristina!', 'Hello, Ana!']
persons.map(greet)
Get all of the persons
array elements, and call the greet()
function with each element as a calling parameter: `greet('Cristina')
, greet('Ana')
.
What’s interesting is that the persons.map(greet)
method can accept the greet()
function as a parameter. In this way greet()
becomes a callback function.
persons.map(greet)
is a function that takes another function as a parameter, so it is called higher-order function.
Callback functionAs a parameter of Higher-order function, the higher-order function performs operations by calling the callback function.
The important thing is that the higher-order function is responsible for calling the callback and providing it with the correct parameters.
In the previous example, the higher-order function persons.map(greet)
is responsible for calling the greet()
function and converting all the elements in the array'Cristina'
and Ana '
as arguments.
This provides a simple rule for identifying callbacks. If you define a function and provide it as a parameter to another function, then this creates a callback.
You can write your own higher-order functions using callbacks. Here is the equivalent version of the array.map()
method:
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)
is a higher-order function because it uses a callback function as parameters, and then call the callback function inside its body: callback(item)
.
Note that regular functions (defined with the keyword function
) or arrow functions (defined with the thick arrow =>
) can also be used as callbacks.
There are two ways to call callbacks: synchronous and asynchronouscallbacks.
Synchronous callbacks are "blocking": the higher-order function does not continue execution until the callback function completes.
For example, call the map()
and greet()
functions.
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'
Among them greet()
is a synchronous callback.
Steps for synchronous callback:
High-order function starts execution: 'map() starts'
Callback function execution: 'greet() called'
. Finally, the higher-order function completes its own execution process: 'map() completed'
Many native JavaScript type methods use synchronous callbacks.
The most commonly used method is array, for example: 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; // => 1
String typestring.replace( callback)
method can also accept synchronously executed callbacks:
// 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'
Asynchronous callbacks are "non-blocking": no need for higher-order functions Wait for the callback to complete to complete its execution. Higher-order functions ensure that callbacks are later executed on specific events.
In the following example, the execution of the later()
function is delayed by 2 seconds:
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)
later()
is an asynchronous callback, Because setTimeout(later, 2000)
starts and completes execution, but later()
executes after 2 seconds.
Steps to call callback asynchronously:
High-order function starts executing: 'setTimeout()starts'
The higher-order function completes its execution: 'setTimeout() completed'
The callback function is executed after 2 seconds: 'later( ) called'
Timer function calls callback asynchronously:
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!'
DOM event The listener also calls the event processing function asynchronously (a subtype of the callback function):
const myButton = document.getElementById('myButton'); myButton.addEventListener('click', function handler() { console.log('Button clicked!'); }); // Logs 'Button clicked!' when the button is clicked
Add before the function definition The special keyword async
will create an asynchronous function:
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学习教程】
The above is the detailed content of In-depth analysis of callback functions in JavaScript (synchronous and asynchronous). For more information, please follow other related articles on the PHP Chinese website!