Коллбек что это
Перейти к содержимому

Коллбек что это

  • автор:

Что такое callback-функция в JavaScript?

Что такое callback-функция в JavaScript? главное изображение

Простыми словами: коллбэк — это функция, которая должна быть выполнена после того, как другая функция завершила выполнение (отсюда и название: callback — функция обратного вызова).

Чуть сложнее: В JavaScript функции — это объекты. Поэтому функции могут принимать другие функции в качестве аргументов, а также возвращать функции в качестве результата. Функции, которые это умеют, называются функциями высшего порядка. А любая функция, которая передается как аргумент, называется callback-функцией.

Зачем нужны коллбэки?

По одной простой причине: JavaScript — это событийно-ориентированный язык. Поэтому вместо того, чтобы ждать ответа для дальнейшего выполнения программы, JavaScript продолжит выполнение, одновременно ожидая других событий. Давайте разберем простой пример:

const first = () =>  console.log(1); >; const second = () =>  console.log(2); >; first(); second(); 

Как вы и ожидаете, функция first выполнится первой, а функция second уже после нее. Поэтому в консоли будет выведен следующий результат:

Пока что все понятно. Но что, если функция first содержит некий код, который не может выполниться немедленно? К примеру, работа с API, где мы отправляем запрос и должны ждать ответа. Чтобы смоделировать такую ситуацию, мы используем функцию setTimeout , которая вызывает функцию после заданного временного промежутка. Мы отсрочим выполнение функции на 500 миллисекунд, как будто бы это запрос к некому API. Теперь код будет выглядеть так:

const first = () =>  // Как будто бы запрос к API setTimeout(() =>  console.log(1); >, 500 ); >; const second = () =>  console.log(2); >; first(); second(); 

Неважно, понимаете ли вы сейчас, как работает setTimeout() . Основная идея — теперь мы отложили исполнение команды console.log(1) на 500 миллисекунд. И что теперь выведет наша программа?

Хотя мы по-прежнему вызываем функцию first первой, ее вывод появился вторым, после вывода функции second . Но JavaScript не нарушает порядок вызова функций, он просто не дожидается ответа от функции first , а сразу двигается дальше — к функции second .

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

Фронтенд-разработчик — с нуля до трудоустройства за 10 месяцев

  • Постоянная поддержка от наставника и учебного центра
  • Помощь с трудоустройством
  • Готовое портфолио к концу обучения
  • Практика с первого урока

Вы получите именно те инструменты и навыки, которые позволят вам найти работу

Создаем коллбэк

Во-первых, откройте консоль разработчика в Google Chrome (Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J), либо свой IDE, либо просто Repl.it , и введите в консоли следующую функцию:

const doHomework = (subject) =>  alert(`Starting my $subject> homework.`); >; 

Мы создали функцию doHomework . Наша функция принимает одну переменную — название предмета, которым мы будем заниматься. Вызовите функцию, набрав следующий текст в консоли:

doHomework('math'); // Выводит алерт: Starting my math homework. 

Теперь давайте добавим в определение функции еще один параметр, это и будет наш коллбэк. Затем вызовем ее, определив функцию-callback в качестве аргумента:

const doHomework = (subject, callback) =>  alert(`Starting my $subject> homework.`); callback(); >; doHomework('math', () =>  alert('Finished my homework'); >); 

Если вы введете этот код в консоли, вы получите два алерта один за другим, в первом будет сообщение о том, что выполнение домашнего задания началось (Starting my math homework.), а во втором — что вы закончили выполнять задание (Finished my homework).

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

const doHomework = (subject, callback) =>  alert(`Starting my $subject> homework.`); callback(); >; const alertFinished = () =>  alert('Finished my homework'); >; doHomework('math', alertFinished); 

Таким образом, результат выполнения этого кода такой же, как и в предыдущем примере, однако сам код немного другой. Как вы видите, мы передали функцию alertFinished как аргумент в функцию doHomework при ее вызове.

Перепишем пример вызова функции с setTimeout для последовательного выполнения функций:

const first = (callback) =>  // Как будто бы запрос к API setTimeout(() =>  console.log(1); callback(); >, 500 ); >; const second = () =>  console.log(2); >; first(second); // 1 // 2 

Пример из реальной жизни

На прошлой неделе я опубликовал статью «Создаем бота для Твиттера в 38 строк кода» . Этот код работает благодаря API Твиттера. И когда мы делаем запрос к API, мы должны дождаться ответа до того, как начнем выполнять с этим ответом какие-то действия. Это прекрасный пример того, как в реальной жизни выглядит коллбэк. Вот как выглядит сам запрос:

T.get('search/tweets', params, (err, data, response) =>  if (!err)  // Происходит какая-то магия > else  console.log(err); > >); 

T.get просто значит, что мы выполняем get запрос к API Твиттера. В запросе три параметра: ‘search/tweets’ – это адрес (роут) запроса, params – наши параметры поиска и в конце передается анонимная функция-callback.

Коллбэк здесь нужен, потому что нам нужно дождаться ответа от сервера до того, как приступим к дальнейшему выполнению кода. Мы не знаем, успешным будет наш запрос или нет, поэтому после отправки параметров поиска на search/tweets через get-запрос, мы просто ждем. Как только Твиттер ответит, выполнится наша callback-функция. Твиттер отправит нам в качестве ответа или объект err (error – ошибка), или объект response. В коллбэке мы можем через if() проверить, был ли запрос успешным или нет, и затем действовать соответственно.

Профессия «Фронтенд-разработчик»

  • Изучите востребованные JavaScript и TypeScript
  • Научитесь создавать пользовательские интерфейсы сайтов и приложений
  • Освойте самый популярный фреймворк JavaScript — React
  • Познакомьтесь с языками веб-разработки HTML и CSS

Колбэк-функция

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

Вот краткий пример:

function greeting(name)  alert("Hello " + name); > function processUserInput(callback)  var name = prompt("Please enter your name."); callback(name); > processUserInput(greeting); 

Выше приведён пример синхронного колбэка, поскольку функция processUserInput выполняется синхронно.

Колбэки часто используются для продолжения выполнения кода после завершения асинхронной операции — они называются асинхронными колбэками.

async function pageLoader(callback)  const data = await fetch("/ru/docs/Glossary/Callback_function"); callback(data); > function onPageLoadingFinished(pageData)  console.log("Page was sucessfully loaded!"); console.log("Response:"); console.log(pageData); > pageLoader(onPageLoadingFinished); 

Вот ещё один пример асинхронного обратного вызова: maps-example.html (живой пример). Он использует Google Maps API и Geolocation API для отображения карты текущего местоположения вашего устройства.

// maps-example.html // Вызов асинхронной функции getCurrentPosition // с передачей callback функции принимающей координаты // в качестве параметра navigator.geolocation.getCurrentPosition(function (position)  var latlng = new google.maps.LatLng( position.coords.latitude, position.coords.longitude, ); var myOptions =  zoom: 8, center: latlng, mapTypeId: google.maps.MapTypeId.TERRAIN, disableDefaultUI: true, >; var map = new google.maps.Map( document.getElementById("map_canvas"), myOptions, ); >); 

Поскольку получение координат устройства из его GPS является асинхронным (мы точно не знаем, когда данные будут возвращены), метод Geolocation.getCurrentPosition() принимает анонимную колбэк-функцию в качестве параметра, которая получает найденные данные координат. Эта функция выполняется только по возвращению данных координат.

Больше информации

Основное

  • Колбэки и события на компонентах
  • Ад обратных вызовов

Callback

Callback – это функция обратного вызова. То есть обратный звонок как способ дополнительной коммуникации с пользователями. Это инструмент маркетинга, который по запросу связывает посетителя сайта с компанией.

Что такое callback?

Вспомогательное приложение (виджет), которое устанавливают на сайте, чтобы автоматически перезванивать клиентам.

Форма обратного звонка может показываться на сайте:

  • когда пользователь нажимает на кнопку callback
  • ярлык виджета автоматически активируется через определенное время сессии пользователя
  • привязан к определённому месту сайта при скроллинге

Когда пользователь кликает на виджет и заполняет форму, ему перезванивают. Чаще всего связь устанавливают через SIP-телефонию.

Зачем нужен обратный звонок для сайта?

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

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

Если пользователь заказал callback, значит он готов выслушать предложения и вести конструктивный диалог. Это уже не является холодным звонком, так как пользователь заинтересован в сотрудничестве. Менеджеру известно, что первый этап пройден, теперь достаточно уточнить, что привлекло внимание. Дальше в ход пойдёт умение вести диалог, ненавязчиво склоняя клиента к тому или иному решению.

Увеличение конверсии происходит не только благодаря общению с менеджерами. Виджет можно настроить в соответствии с триггерами пользователей. Например, он может появляться, когда посетитель собирается покинуть страницу: прокручивает страницу к началу или наводит курсор на кнопку закрытия вкладки. Такой подход к работе сайта снижает количество отказов.

Большинство людей не обращаются по предоставленным на сайте контактам из-за того, что им:

  • бывает сложно найти информацию о контактных данных
  • неудобен предложенный вариант связи
  • некомфортно обращаться первыми

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

  • по качеству товара или услуги
  • по особенностям доставки (удалённое расположение, неудобное время доставки, нет представления о том, как она организована и т. п.)
  • по разным техническим параметрам представленным или чаще всего НЕ представленным на сайте
  • по действию акционных предложений
  • и множество прочих вопросов, которые несомненно влияют на выбор и лояльность клиента

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

Как работает callback?

Доступные функции обратного звонка отличаются в зависимости от сервиса, который занимался разработкой callback. Однако принцип работы у каждого из них подобен и выглядит следующим образом:

  1. На экране появляется всплывающее окно с пустой строкой для ввода номера телефона и предложением обратной связи
  2. Пользователь вводит номер
  3. Система обратного звонка отправляет запрос (дозванивается) по номеру компании
  4. Как только менеджер берет трубку, с обратной стороны производится набор номера, оставленного посетителем.

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

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

Как установить callback на свой сайт?

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

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

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

  • запись и тегирование звонков
  • обработку заявок в нерабочее время
  • сбор заявок из соц. сетей – Facebook и ВКонтакте
  • голосовое оповещение для операторов
  • равномерное распределение звонков между операторами, чтобы ни один звонок не потерялся
  • DTMF. Вызов клиенту идет только при ответе оператора

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

Каким должен быть callback?

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

Исследования показали, что виджет работает достаточно результативно, если окно появляется после пятой секунды от захода пользователя на сайт. Время появления окна можно регулировать в настройках.

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

  • с какого сайта человек попал на страницу компании
  • где была заказана услуга обратной связи
  • последние просмотренные пользователем данные на сайте

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

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

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

По последним данным с началом использования callback на сайте происходит:

  • Рост числа обращений. Показатель, конечно, зависит от специфики ниши и в некоторых случаях может доходить до отметки в 47%
  • Рост количества положительно завершенных разговоров. Действительно, к телефонным обращениям напрямую в компанию или через рекламу, добавляются звонки, по сути, «тёплым клиентам», про которых уже известно, что примерно их интересует. Следовательно и конверсия телефонных звонков увеличивается
  • Стимул для начала общения у пользователей, которые по каким-то причинам не хотят звонить первыми. Довольно большому количеству людей психологически сложно даётся этот шаг – позвонить самому. Они ищут причины и оправдания. Функция callback спасает их от сложностей первого общения
  • Снижение показателя отказов из-за возможности получения дополнительной информации и ответов на вопросы. Своевременное уточнение информации и человеческий подход являются залогом успешного звонка в данном случае
  • Возможность моментальной обратной связи. Люди довольно часто откладывают покупку, а затем и вовсе забывают про нее. Виджет косвенно подталкивает к совершению целевого действия, без привлечения навязчивых «холодных звонков»

Вывод

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

Введение: колбэки

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

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

Тем не менее, мы все равно попытаемся максимально доходчиво всё разъяснить. Ничего особо сложного в плане браузера не будет.

Многие действия в JavaScript асинхронные.

Например, рассмотрим функцию loadScript(src) :

function loadScript(src)

Эта функция загружает на страницу новый скрипт. Когда в тело документа добавится конструкция , браузер загрузит скрипт и выполнит его.

Вот пример использования этой функции:

// загрузит и выполнит скрипт loadScript('/my/script.js');

Такие функции называют «асинхронными», потому что действие (загрузка скрипта) будет завершено не сейчас, а потом.

Если после вызова loadScript(…) есть какой-то код, то он не будет ждать, пока скрипт загрузится.

loadScript('/my/script.js'); // код, написанный после вызова функции loadScript, // не будет дожидаться полной загрузки скрипта // . 

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

Но если мы просто вызовем эту функцию после loadScript(…) , у нас ничего не выйдет:

loadScript('/my/script.js'); // в скрипте есть "function newFunction() " newFunction(); // такой функции не существует!

Действительно, ведь у браузера не было времени загрузить скрипт. Сейчас функция loadScript никак не позволяет отследить момент загрузки. Скрипт загружается, а потом выполняется. Но нам нужно точно знать, когда это произойдёт, чтобы использовать функции и переменные из этого скрипта.

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

function loadScript(src, callback) < let script = document.createElement('script'); script.src = src; script.onload = () =>callback(script); document.head.append(script); >

Событие onload описано в статье Загрузка ресурсов: onload и onerror, оно в основном выполняет функцию после загрузки и выполнения скрипта.

Теперь, если мы хотим вызвать функцию из скрипта, нужно делать это в колбэке:

loadScript('/my/script.js', function() < // эта функция вызовется после того, как загрузится скрипт newFunction(); // теперь всё работает . >);

Смысл такой: вторым аргументом передаётся функция (обычно анонимная), которая выполняется по завершении действия.

Возьмём для примера реальный скрипт с библиотекой функций:

function loadScript(src, callback) < let script = document.createElement('script'); script.src = src; script.onload = () =>callback(script); document.head.append(script); > loadScript('https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.2.0/lodash.js', script => < alert(`Здорово, скрипт $загрузился`); alert( _ ); // функция, объявленная в загруженном скрипте >);

Такое написание называют асинхронным программированием с использованием колбэков. В функции, которые выполняют какие-либо асинхронные операции, передаётся аргумент callback — функция, которая будет вызвана по завершению асинхронного действия.

Мы поступили похожим образом в loadScript , но это, конечно, распространённый подход.

Колбэк в колбэке

Как нам загрузить два скрипта один за другим: сначала первый, а за ним второй?

Первое, что приходит в голову, вызвать loadScript ещё раз уже внутри колбэка, вот так:

loadScript('/my/script.js', function(script) < alert(`Здорово, скрипт $загрузился, загрузим ещё один`); loadScript('/my/script2.js', function(script) < alert(`Здорово, второй скрипт загрузился`); >); >);

Когда внешняя функция loadScript выполнится, вызовется та, что внутри колбэка.

А что если нам нужно загрузить ещё один скрипт.

loadScript('/my/script.js', function(script) < loadScript('/my/script2.js', function(script) < loadScript('/my/script3.js', function(script) < // . и так далее, пока все скрипты не будут загружены >); >) >);

Каждое новое действие мы вынуждены вызывать внутри колбэка. Этот вариант подойдёт, когда у нас одно-два действия, но для большего количества уже не удобно. Альтернативные подходы мы скоро разберём.

Перехват ошибок

В примерах выше мы не думали об ошибках. А что если загрузить скрипт не удалось? Колбэк должен уметь реагировать на возможные проблемы.

Ниже улучшенная версия loadScript , которая умеет отслеживать ошибки загрузки:

function loadScript(src, callback) < let script = document.createElement('script'); script.src = src; script.onload = () =>callback(null, script); script.onerror = () => callback(new Error(`Не удалось загрузить скрипт $`)); document.head.append(script); >

Мы вызываем callback(null, script) в случае успешной загрузки и callback(error) , если загрузить скрипт не удалось.

loadScript('/my/script.js', function(error, script) < if (error) < // обрабатываем ошибку >else < // скрипт успешно загружен >>);

Опять же, подход, который мы использовали в loadScript , также распространён и называется «колбэк с первым аргументом-ошибкой» («error-first callback»).

  1. Первый аргумент функции callback зарезервирован для ошибки. В этом случае вызов выглядит вот так: callback(err) .
  2. Второй и последующие аргументы — для результатов выполнения. В этом случае вызов выглядит вот так: callback(null, result1, result2…) .

Одна и та же функция callback используется и для информирования об ошибке, и для передачи результатов.

Адская пирамида вызовов

На первый взгляд это рабочий способ написания асинхронного кода. Так и есть. Для одного или двух вложенных вызовов всё выглядит нормально.

Но для нескольких асинхронных действий, которые нужно выполнить друг за другом, код выглядит вот так:

loadScript('1.js', function(error, script) < if (error) < handleError(error); >else < // . loadScript('2.js', function(error, script) < if (error) < handleError(error); >else < // . loadScript('3.js', function(error, script) < if (error) < handleError(error); >else < // . и так далее, пока все скрипты не будут загружены (*) >>); > >) > >);
  1. Мы загружаем 1.js . Продолжаем, если нет ошибок.
  2. Мы загружаем 2.js . Продолжаем, если нет ошибок.
  3. Мы загружаем 3.js . Продолжаем, если нет ошибок. И так далее (*) .

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

Иногда это называют «адом колбэков» или «адской пирамидой колбэков».

Пирамида вложенных вызовов растёт вправо с каждым асинхронным действием. В итоге вы сами будете путаться, где что есть.

Такой подход к написанию кода не приветствуется.

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

loadScript('1.js', step1); function step1(error, script) < if (error) < handleError(error); >else < // . loadScript('2.js', step2); >> function step2(error, script) < if (error) < handleError(error); >else < // . loadScript('3.js', step3); >> function step3(error, script) < if (error) < handleError(error); >else < // . и так далее, пока все скрипты не будут загружены (*) >>;

Заметили? Этот код делает всё то же самое, но вложенность отсутствует, потому что все действия вынесены в отдельные функции.

Код абсолютно рабочий, но кажется разорванным на куски. Его трудно читать, вы наверняка заметили это. Приходится прыгать глазами между кусками кода, когда пытаешься его прочесть. Это неудобно, особенно, если читатель не знаком с кодом и не знает, что за чем следует.

Кроме того, все функции step* одноразовые, и созданы лишь только, чтобы избавиться от «адской пирамиды вызовов». Никто не будет их переиспользовать где-либо ещё. Таким образом, мы, кроме всего прочего, засоряем пространство имён.

Нужно найти способ получше.

К счастью, такие способы существуют. Один из лучших — использовать промисы, о которых рассказано в следующей главе.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *