#javascript
#javascript
Вопрос:
Я читал о функциях обратного вызова здесь (также в онлайн-курсе, в котором я участвую), и теперь я застрял. Причина в том, что я не могу понять, зачем мне использовать функции обратного вызова, если я могу их просто вызвать. Примеры ниже:
1 — Использование функций обратного вызова:
function showArticle(id, callbackSuccess, callbackError){
if (true){
callbackSuccess("This is a callback function", "It is very utilized.");
} else {
callbackError("Error on data recovery.");
}
}
var callbackSuccess = function(title, description){
document.write("<h1>" title "</h1>");
document.write("<hr>");
document.write("<p>" description "</p>");
}
var callbackError = function(error){
document.write("<p><b>Erro:</b>" error "</p>");
}
showArticle(1, callbackSuccess, callbackError);
2 — Вот мой код, не использующий функции обратного вызова и имеющий те же результаты:
function showArticle(id){
if (true){
callbackSuccess("This is a callback function", "It is very utilized.");
} else {
callbackError("Error on data recovery.");
}
}
var callbackSuccess = function(title, description){
document.write("<h1>" title "</h1>");
document.write("<hr>");
document.write("<p>" description "</p>");
}
var callbackError = function(error){
document.write("<p><b>Erro:</b>" error "</p>");
}
showArticle(1);
Почему я должен использовать функции обратного вызова, а не просто вызывать их в примере 2?
Ответ №1:
Вы правы, в функциях обратного вызова в приведенном вами примере нет смысла, но обычно функции обратного вызова используются не так.
Обычно используются обратные вызовы:
- С помощью функций итерации, сопоставления или фильтрации, которые вызывают ваш обратный вызов для каждого элемента в массиве, списке или другом контейнере
- С помощью функций, которые выполняют асинхронную работу, которые вызывают ваш обратный вызов, когда работа успешно завершена, сбой или оба (в зависимости от стиля API, который вы вызываете)
- Функции, которые принимают обратные вызовы, будут вызывать, когда или если что-то произойдет, например, обработчик
click
событий для элемента DOM
… но есть и другие категории.
filter
Функция в массивах является примером # 1: она вызывает обратный вызов для каждой записи в массиве, используя возвращаемое значение обратного вызова, чтобы решить, должна ли запись находиться в новом, отфильтрованном массиве, который она возвращает:
const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const odds = numbers.filter(num => {
console.log(`callback called with ${num}`); // logs 10 times
return num % 2;
});
console.log(odds); // [1, 3, 5, 7, 9]
Методы Promise then
, catch
, и finally
являются примерами # 2. Предположим, у нас есть startSomethingAsynchronous
функция, которая возвращает обещание. Вот как могут быть настроены обработчики выполнения и отклонения (обратные вызовы):
startSomethingAsynchronous() // Starts an asynchronous process
.then(result => { // <−
// ...do something with the result... // − This is a fulfillment handler
}) // <−
.catch(error => { // <−
// ...report or handle error... // − This is a rejection handler
}); // <−
Обработчик выполнения вызывается, если обещание от startSomethingAsynchronous()
выполнено (успешно завершено). Обработчик отклонения вызывается, если это обещание отклонено (сбой), или если это обещание выполнено, но обещание, возвращенное then
rejects (например, из-за ошибки в обработчике выполнения). (Объединение подобных вещей в цепочки довольно распространено, но есть много других способов использования promises, это всего лишь один пример.)
addEventListener
Функция в DOM является примером # 3:
document.querySelector("input[type=button]")
.addEventListener("click", function() {
console.log("Clicked!"); // logs as many times as you click the button
});
<input type="button" value="Click Me">
Ответ №2:
JavaScript выполняет код последовательно в порядке сверху вниз. Однако в некоторых случаях код выполняется (или должен выполняться) после того, как происходит что-то еще, а также не последовательно. Это называется асинхронным программированием.
Обратные вызовы гарантируют, что функция не будет запущена до завершения задачи, а будет запущена сразу после завершения задачи. Это помогает нам разрабатывать асинхронный код JavaScript и защищает нас от проблем и ошибок.
В JavaScript способ создания функции обратного вызова — передать ее в качестве параметра другой функции, а затем вызвать ее обратно сразу после того, как что-то произошло или какая-то задача выполнена.
— freecodecamp.org
Вы можете прочитать больше здесь.
Ответ №3:
Приведенные выше ответы верны. Моя — это просто упрощение одной из причин (асинхронный характер)
Обратите внимание, что НЕ все последовательно.
- Вызов базы данных может занять 100 мс, 200 мс или 1 сек для возврата данных.
- Чтение файла, размер которого вам неизвестен, может занять
X
несколько секунд.
В тех случаях, когда вы не знаете, сколько времени займет операция, вы используете подход обратного вызова, и это функция JavaScript.
Некоторые языки блокируют поток (я буду ждать вызова базы данных) или создавать потоки (я буду выполнять эти операции в другом «процессе»)
JS будет содержать обещания и обратные вызовы.