Обратный вызов - это функция, которая передается в другую функцию в качестве аргумента, который может быть вызван позже внутри функции.
Синхронные обратные вызовы
Синхронный означает, что операторы кода выполняются последовательно друг за другом.
function print(number, result) { console.log(`${number} is ${result}`); } function checkEvenOrOdd(number, callback) { const result = (number % 2 === 0) ? 'Even' : 'Odd'; callback(number, result); } checkEvenOrOdd(56, print); // 56 is Even
Здесь обратный вызов выполняется немедленно и не ожидает завершения какой-либо асинхронной операции. Вот почему это синхронный обратный вызов.
Асинхронные обратные вызовы
Если обратный вызов выполняется после завершения асинхронной операции, то это асинхронный обратный вызов.
Давайте посмотрим на один пример, где мы возьмем заказ и распечатаем его.
function takeOrder() { setTimeout(() => { return (Math.random() * 10) <= 5 ? 'Coffee' : 'Tea'; }, 1000); } let order = takeOrder(); console.log('Order is for: ' + order); // Order is for: undefined
Здесь, в функции takeOrder
, setTimeout
запустится через 1 секунду, и к этому времени оператор console.log
уже будет выполнен, поэтому напечатанное значение порядка как неопределенное.
Теперь мы можем решить эту проблему, если сможем записать наше сообщение в консоль только после того, как данные будут возвращены из takeOrder
. Это можно сделать, передав функцию обратного вызова takeOrder
, которая будет вызываться внутри функции takeOrder
.
function takeOrder(callback) { setTimeout(() => { const order = (Math.random() * 10) <= 5 ? 'Coffee' : 'Tea'; callback(order); }, 1000); } takeOrder((order) => { console.log('Order is for: ' + order); }); // Order is for: Tea
Здесь через 1 секунду будет вызвана функция обратного вызова, и оператор консоли будет выполнен с правильным значением порядка.
Примечание. Вывод функции
takeOrder
может отличаться в вашем случае, поскольку мы используемMath.random()
для определения стоимости заказа.
Обработка ошибок с помощью обратных вызовов
Мы можем передавать разные обратные вызовы как для успешных, так и для неудачных сценариев.
function takeOrder(success, failure) { setTimeout(() => { const random = (Math.random() * 10); if(random < 8) { const order = random < 4 ? 'Coffee' : 'Tea'; success(order); } else { failure('Order Not Available'); } }, 1000); } takeOrder( (order) => { console.log('Order is for: ' + order); }, (error) => { console.log(error); } );
Вложенные обратные вызовы
Давайте посмотрим на процесс заказа один за другим.
function takeOrder(callback) { setTimeout(() => { const order = (Math.random() * 10) <= 5 ? 'Coffee' : 'Tea'; callback(order); }, 1000); } function makeOrder(order, callback) { setTimeout(() => { callback(order + ' is prepared'); }, 1000); } function serveOrder(order, callback) { setTimeout(() => { callback(order + ' is served'); }, 1000); } takeOrder((order) => { console.log('Order is for: ' + order); makeOrder(order, (orderStatus) => { console.log(orderStatus); serveOrder(order, (orderStatus) => { console.log(orderStatus); }) }) });
Выход
Order is for: Coffee Coffee is prepared Coffee is served
Здесь makeOrder
вызывается, когда приходит ответ от takeOrder
. Аналогично serveOrder
вызывается, когда приходит ответ от makeOrder
. Здесь мы вкладываем обратные вызовы друг в друга для последовательного выполнения функций.
Если вложенность обратных вызовов увеличивается, это называется адом обратных вызовов, где трудно управлять обратными вызовами, и это снижает удобочитаемость кода. Взгляните на пример ада обратного вызова.
takeOrder((order) => { makeOrder(order, () => { serveOrder(order, () => { provideBill(order, () => { takeBill(order, () => { // some more callbacks }) }) }) }) });
Этот ад обратного вызова можно исправить с помощью обещания и async / await.
В JavaScript есть несколько встроенных методов, которые принимают обратный вызов в качестве аргумента.
// Array.map() array.map((element) => { // your code here }); // setTimeout setTimeout(() => { // your code here }, timeout);
Давайте посмотрим на некоторые другие методы, которые принимают обратный вызов.
Array.filter()
, Array.reduce()
, Array.find()
, Array.sort()
, Array.forEach()
, setInterval()
, addEventListener()
, Promise.then()
, Promise.catch()
и т. Д.
Вам также может понравиться
- Краткое руководство по обещаниям в JavaScript
- Понимание async и await в JavaScript
- JavaScript Fetch API для выполнения HTTP-запросов
- 20 сокращенных приемов JavaScript, которые сэкономят ваше время
Спасибо за уделенное время ☺️
Для других блогов о веб-разработке посетите jscurious.com