Основы функции обратного вызова и варианты использования в JavaScript

Во время моего путешествия по JavaScript и нескольких дней работы с React мне пришлось привыкнуть к функциям обратного вызова. Невозможно было избежать его существования и слепо пользоваться им, не понимая. Чтобы понять функцию обратного вызова, нам нужно немного узнать о функциях. Здесь я хочу поговорить о выражении функции, функции стрелки и функции обратного вызова.

Что такое функция обратного вызова?

Согласно документу MDN:

Функция обратного вызова - это функция, переданная в другую функцию в качестве аргумента, которая затем вызывается внутри внешней функции для выполнения какой-либо процедуры или действия.

В JavaScript функции являются объектами, что означает, что, как и любые другие объекты, они могут быть присвоены переменной и переданы в качестве аргумента другой функции. Вкратце, функция обратного вызова - это функция, которая предоставляется как параметр для других методов, таких как метод forEach или метод addEventListener, и вызывается в определенный момент времени.

Передача функций в качестве аргументов

Итак, как мы это сделаем? Давайте посмотрим на примере ниже:

document.addEventListener(‘click’,whoAmI);
//whoAmI Function Declaration(Function Statement)
function whoAmI(event){
  console.log(event.target.tagName)
}

Мы прикрепили прослушиватель событий «click» к документу с функцией whoAmI в качестве параметра, который регистрирует имя тега выбранной цели. Каждый раз, когда происходит «щелчок», whoAmI будет вызываться функция с аргументом event. Мы вызываем whoAmI функцию обратного вызова.

Когда мы вызываем функцию по ее имени, за которым следует (), мы говорим функции выполнить свой код. Когда мы называем функцию или передаем функцию без символа (), функция не выполняется. Функция обратного вызова не выполняется сразу. Вместо этого метод addEventListener выполняет функцию при возникновении события.

Я хочу упомянуть еще одну вещь: поскольку мы использовали объявление функции, мы смогли вызвать функцию thewhoAmI до того, как она была объявлена. Это волшебство подъема в JS. Но с выражением функции его не поднимают. Поэтому порядок написания функциональных выражений и их использования в качестве обратного вызова будет иметь решающее значение.

//Function Expression : logs tag name of clicked element
const whoAmI = function(event){
  console.log(event.target.tagName)
}
//Arrow Function Expression : logs mouse X position 
const whereAmI = (event) => {
  console.log("X pos : ",event.clientX)
}
document.addEventListener(‘click’,whoAmI);
document.addEventListener('mousemove',whereAmI);

* Можно поднять только функцию объявления функции (вызывается перед объявлением)

ссылки на объявление функции, выражение и подъем:







Встроенная функция обратного вызова

whoAmI функция довольно проста, поэтому мы можем написать whoAmI функцию обратного вызова как встроенную функцию. Мы называем это анонимной функцией, потому что у этой функции нет имени. Записать его можно двумя способами:

//anonymous function
document.addEventListener(‘click’,function(event){console.log(event.target.tagName)});
//anonymous arrow function 
document.addEventListener(‘click’,(event)=>console.log(event.target.tagName));

Но если у вас есть более длинные блоки кода, вы захотите вынуть их и сохранить как переменную и ссылаться на функцию обратного вызова с именем переменной.

//saving anonymous function to a variable
const whoAmI = function(event){
  console.log(event.target.tagName)
}
//saving arrow function to a variable
//(whoAmIArrow and whoAmI are exactly same)
const whoAmIArrow =(event)=>{
  console.log(event.target.tagName)
}
document.addEventListener(‘click’,whoAmI);

ссылка на функцию стрелки:



Асинхронный и синхронный обратный вызов

Существует два типа функций обратного вызова: асинхронные и синхронные. Функция синхронного обратного вызова запускается как обычный JavaScript по очереди, в то время как функция асинхронного обратного вызова запускается, когда она вызывается после выполнения задания.

Как и в наших примерах метода «eventListener», мы передали функцию обратного вызова, которая выполняется только после срабатывания события. Наша функция обратного вызова будет ждать до первой части, когда будет возвращено «event». Другой пример - использование API. Когда вы запрашиваете данные из API с помощью метода «fetch», вы не хотите, чтобы все другие функции в вашем скрипте дожидались, пока вы вернете свои данные. Это создаст долгую задержку «ничего не происходит», что заставит пользователя уйти от вашего приложения.

Хватит читать, теперь давайте сами в этом убедимся. Здесь мы собираемся использовать статические данные и запрос API для объяснения синхронного и асинхронного. Во-первых, давайте посмотрим на синхронный обратный вызов со статическими данными.

Эта logger функция принимает массив объекта и функцию обратного вызова. В функции logger он выполняет итерацию по массиву объекта и вызывает с ним функцию обратного вызова. Результат показывает, что он вызвал функции по порядку.

const peopleInSpace = {
  "message": "success", 
  "number": 5, 
  "people": [{"craft": "ISS", "name": "Chris Cassidy"}, 
             {"craft": "ISS", "name": "Anatoly Ivanishin"},
             {"craft": "ISS", "name": "Ivan Vagner"},
             {"craft": "ISS", "name": "Doug Hurley"},
             {"craft": "ISS", "name": "Bob Behnken"}
            ]
}
//logger function that takes in an array and a function
function logger(peopleArray,callback) {
  console.log("1.In logger function")
  //iterate through peopleArray with callback function
  peopleArray.forEach(personObj => callback(personObj))
}
//callback function that logs value of object with key
function callback(personObj){
  console.log("2. In callback function")
  //Destructuring keys from personObj which is 'craft' and 'name'
  let [key1, key2] = Object.keys(personObj)
  console.log(`${personObj[key2]} is on ${personObj[key1]}`)
}
logger(peopleInSpace.people, callback)
console.log("3. After logger function")
/*result
1.In logger function
2. In callback function
Chris Cassidy is on ISS
2. In callback function
Anatoly Ivanishin is on ISS
2. In callback function
Ivan Vagner is on ISS
2. In callback function
Doug Hurley is on ISS
2. In callback function
Bob Behnken is on ISS
3. After logger function
*/

Давайте воспользуемся методом fetch ​​ и посмотрим, как он работает. Объект peopleInSpace на самом деле представляет собой данные JSON, которые вы получаете из API открытых уведомлений. Мы используем выборку с адресом http://api.open-notify.org/iss-now.json. Поскольку метод ‘fetch’ является асинхронной функцией, console.log("3. After logger function") регистрируется первым.

fetch('http://api.open-notify.org/iss-now.json')
  .then(res => res.json())
  .then(json => logger(json.people, callback));
//logger function that takes in an array and a function
function logger(peopleArray,callback) {
  console.log("1.In logger function")
  //iterate through peopleArray with callback function
  peopleArray.forEach(personObj => callback(personObj))
}
//callback function that logs value of object with key
function callback(personObj){
  console.log("2. In callback function")
  //Destructuring keys from personObj which is 'craft' and 'name'
  let [key1, key2] = Object.keys(personObj)
  console.log(`${personObj[key2]} is on ${personObj[key1]}`)
}
console.log("3. After logger function")
/*result
3. After logger function
1.In logger function
2. In callback function
Chris Cassidy is on ISS
2. In callback function
Anatoly Ivanishin is on ISS
2. In callback function
Ivan Vagner is on ISS
2. In callback function
Doug Hurley is on ISS
2. In callback function
Bob Behnken is on ISS
*/

* примечание: если вы хотите знать, что деструктурирует в ES6, прочтите ниже:







Написание функций с обратными вызовами

Последнее, что я хочу вам показать, это как написать собственную функцию обратного вызова. До сих пор мы использовали функции обратного вызова для методов JavaScript, которые принимают функцию обратного вызова в качестве аргумента. Чтобы попрактиковаться, мы напишем нашу собственную функцию, которая принимает функцию обратного вызова.

Вот простой пример функции basicMath, которая принимает функцию обратного вызова в качестве аргумента. Это общая функция, которая возвращает результат любой операции, определенной в функции обратного вызова с num1 и num2.

function basicMath(num1, num2, callback) {
 let result = callback(num1, num2)
 console.log('The result is: ',result)
}

Чтобы вызвать нашу basicMath функцию, передайте два числовых аргумента, а затем функцию в качестве третьего аргумента:

//passing multiply callback in anonymous function expression
basicMath(3, 5, function(num1, num2){
 let result = num1 * num2
 return result
})

Мы можем взять функцию обратного вызова и сослаться на нее в функции thebasicMath:

function basicMath(num1, num2, callback) {
 let result = callback(num1, num2)
 console.log('The result is: ',result)
}
//multiply callback in arrow function expression
const multiplyArrow = (num1, num2) => num1*num2
//multiply callback in anonymous function expression save in variable
const multiply = function(num1, num2){ return num1*num2 }
//calling basicMath function with multiplyArrow
basicMath(5,2,multiplyArrow)
//calling basicMath function with multiply
basicMath(5,2,multiply)

Обе функции multiplyArrow и multiply делают одно и то же. Просто написано иначе. Как видите, при использовании стрелочной функции в одной строке вы можете опустить {}.. Он неявно возвращает выражение, поэтому return не требуется.

Вот полный пример кода того, что мы только что сделали выше. Поиграйте с кодом и подумайте, как сделать функцию обратного вызова многоразовой.

Спасибо, что прочитали это, и я надеюсь, что теперь вы лучше знакомы с функцией обратного вызова. О функции обратного вызова можно узнать гораздо больше. Пожалуйста, посмотрите ссылки ниже для более глубокого погружения.

дополнительная информация о функциях, функциях стрелки, обратном вызове и обещаниях, async / await:



Функции
В общем, функция - это« подпрограмма
, которая может быть вызвана внешним кодом (или внутренним в случае… developer.mozilla.org »