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

Начнем с классического примера функции обратного вызова.

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

          () =>{
console.log('two seconds has passed')
}

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

Смущение

Многие люди думают, что каждый используемый шаблон обратного вызова является асинхронным. Это неверно, потому что в приведенном выше примере setTimeout является асинхронной функцией API узла, но также forEach и filter используют шаблон обратного вызова, но внутри этих методов ничего асинхронного не происходит.

Пример неасинхронного обратного вызова:

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

Преимущество определения собственной функции обратного вызова

Вопрос в том, почему так важно использовать функцию обратного вызова и как это может помочь нам улучшить наш код. Представьте, что у нас есть функция «geocode ()», которая принимает в качестве аргумента местоположение и возвращает нам некоторые координаты. Предполагая, что мы хотим использовать эту функцию в нескольких файлах в нашем приложении, давайте посмотрим, как структура этой функции с использованием обратного вызова и функции без обратного вызова может повлиять на нашу функциональность.

В этом примере мы видим, что наш метод будет работать нормально и вернуть то, что нам нужно, но внутри он не выполняет никакой асинхронной логики. Если мы хотим реализовать некоторую задержку в ответе, например, используя setTimeout внутри этой функции, давайте посмотрим, что произойдет:

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

Использование функции обратного вызова в качестве аргумента

давайте посмотрим, как эта функция будет работать с функцией обратного вызова, переданной в качестве аргумента:

В приведенном выше примере мы передали функцию обратного вызова в качестве второго аргумента, а вместо этого, чтобы дать возвращаемое значение, мы передали данные внутри функции обратного вызова. Когда мы вызываем функцию в нашем приложении, она выполняет операцию Asychrones, которая позволяет нам получить нужные данные и выполнить позже другую операцию, например, вызвать setTimeout и отобразить данные через 2 секунды.

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

В приведенном выше примере мы определили функцию «doSomeCalculation ()», которая принимает в качестве аргументов два числа и функцию обратного вызова. Когда мы вызываем функцию ниже, мы можем выполнять другую операцию с возвращаемым значением, например, умножать или делить каждый раз с другим значением, без ограничений в определении операции внутри основной функции.

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