An article to understand the callback in JavaScript

  • 2021-10-16 01:00:11
  • OfStack

Preface

Callback function is one of the concepts that every front-end programmer should know. Callbacks can be used in arrays, timer functions, promise, and event handling.

This article will explain the concept of callback function and help you distinguish two kinds of callbacks: synchronous and asynchronous.

Callback function

First, write a function to greet people.

You only need to create a function greet (name) that accepts the name parameter. This function should return a greeting message:


function greet(name) {
 return `Hello, ${name}!`;
}

greet('Cristina'); // => 'Hello, Cristina!'

What should I do if I say hello to many people? It can be achieved with a special array method array. map ():


const persons = ['Cristina', 'Ana'];

const messages = persons.map(greet);
messages; // => ['Hello, Cristina!', 'Hello, Ana!'] 

persons. map (greet) takes all the elements of the persons array and calls the greet () function with each element as a call parameter: greet ('Cristina'), greet ('Ana').

Interestingly, the persons. map (greet) method can take the greet () function as an argument. In this way, greet () becomes a callback function.

persons. map (greet) is a function that takes another function as an argument and is therefore called a higher order function.

The callback function is an argument to a higher-order function, which performs an operation by calling the callback function.

What is important is that higher-order functions are responsible for calling callbacks and providing them with correct parameters.

In the previous example, the higher-order function persons. map (greet) is responsible for calling the greet () function and taking all the elements' Cristina'and 'Ana'in the array as arguments, respectively.

This provides a simple rule for identifying callbacks. If you define a function and provide it as an argument to another function, then you create a callback.

You can write your own higher-order functions that use callbacks. The following 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 takes a callback function as an argument and then calls the callback function inside its body: callback (item).

Note that the regular function (defined with the keyword function) or the arrow function (with the thick arrow = > Definition can also be used as a callback.

Synchronous callback

There are two ways to call callbacks: synchronous and asynchronous callbacks.

Synchronous callbacks are "blocked": higher-order functions do not continue to execute until the callback function is completed.

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'

Where greet () is a synchronous callback.

To synchronize callbacks:

Higher order function starts executing: 'map () starts' Callback function execution: 'greet () called' Finally, the higher order function completes its own execution process: 'map () completed'

Example of synchronous callback

Many native JavaScript-type methods use synchronous callbacks.

The most commonly used methods are array, such as 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-type string. replace (callback) methods can also accept synchronized 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 callback

Asynchronous callbacks are "non-blocking": higher-order functions can complete their execution without waiting for the callback to complete. Higher-order functions ensure that callbacks are executed later 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.

To invoke a callback asynchronously:

Higher order function starts executing: 'setTimeout () starts' The higher order function completes its execution: 'setTimeout () completed' The callback function executes after 2 seconds: 'later () called'

Examples of asynchronous callbacks

The timer function calls the 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 listeners also call event handlers (subtypes of callback functions) asynchronously:


const myButton = document.getElementById('myButton');

myButton.addEventListener('click', function handler() {
 console.log('Button clicked!');
});
// Logs 'Button clicked!' when the button is clicked

4. Asynchronous callback functions versus asynchronous functions

Adding the special keyword async before the function definition creates 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 () is asynchronous because it is prefixed with async. Function await fetch ('https://api. github. com/users? per_page=5 ') Get the first 5 users from GitHub. JSON data is then extracted from the response object: await resp. json ().

Asynchronous functions are syntax sugar on top of promise. When the expression await is encountered < promise > (Calling fetch () returns 1 promise), the asynchronous function pauses until promise is resolved.

Asynchronous callback function and asynchronous function are two different terms.

Asynchronous callback functions are executed by higher-order functions in a non-blocking manner. But the asynchronous function is waiting for promise (await < promise > ) Pause execution while parsing.

But you can use asynchronous functions as asynchronous callbacks!

Let's set the asynchronous function fetch UserNames () as an asynchronous callback that can be called with the click of a button:


const persons = ['Cristina', 'Ana'];

const messages = persons.map(greet);
messages; // => ['Hello, Cristina!', 'Hello, Ana!'] 

0

Summarize

A callback is a function that can be passed as an argument to another function (higher order function) for execution.

There are two kinds of callback functions: synchronous and asynchronous.

Synchronous callbacks are blocked.

Asynchronous callbacks are non-blocking.

Finally, to test you: Is setTimeout (callback, 0) synchronous or asynchronous when executing callback?


Related articles: