Небольшой размер урока Javascript, который можно закончить за 3-5 минут!
Пропустили предыдущий урок по встроенным функциям и классам? Иди сюда".

Контекст: вам нужно выучить JavaScript менее чем за 3 недели до собеседования.

Мы все были там. В колледже я изучал Python и Java, и во время второго собеседования в моей жизни мой тогдашний начальник спросил меня:

Вы умеете программировать через интерфейс? Вы знаете какой-нибудь Javascript?

Я честно ответил, что не знаю JavaScript.

Хорошо, прочтите эту книгу и приходите учиться на работе

Прежде чем я это узнаю, я занимаюсь JavaScript 12 лет!
На сегодняшнем уроке я расскажу вам о обратных вызовах / получении данных / работе с JSON.

Перед тем, как прыгнуть в

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

  • Откройте новую пустую вкладку
  • Щелкните правой кнопкой мыши и выберите Проверить.
  • Выберите вкладку Консоль, увидите небольшую ›синюю стрелку.
  • Давай приготовим.

Создайте свой собственный фотоколлаж Doggy Photo Collage

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

Напишите функцию, загружающую 50 (или более!) Фотографий собак, и разместите их в браузере. Когда мы нажимаем на любое из изображений, они говорят Гав!

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

  1. Где взять изображения собак?
  2. Как сделать так, чтобы изображение одной собаки отображалось на вкладке и говорило «Гав!» при нажатии?
  3. Как мне сделать 1 и 2 50 раз? Ой, подождите, я уже выучил циклы на уроке 2. Ничего страшного.

Загрузка данных

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

Попробуйте загрузить этот URL в новой вкладке: https://api.thedogapi.com/v1/images/search

У вас должно получиться что-то вроде этого:

[{"breeds":[{"weight":{"imperial":"44 - 62","metric":"20 - 28"},"height":{"imperial":"17 - 20","metric":"43 - 51"},"id":21,"name":"Australian Cattle Dog","country_code":"AU","bred_for":"Cattle herding, herding trials","breed_group":"Herding","life_span":"12 - 14 years","temperament":"Cautious, Energetic, Loyal, Obedient, Protective, Brave"}],"id":"9AXHhr6LG","url":"https://cdn2.thedogapi.com/images/9AXHhr6LG.jpg","width":1080,"height":1080}]

Это выглядит сложно, но вы можете сделать его красивее с помощью консоли Chrome:

> var data = [{"breeds":[{"weight":{"imperial":"44 - 62","metric":"20 - 28"},"height":{"imperial":"17 - 20","metric":"43 - 51"},"id":21,"name":"Australian Cattle Dog","country_code":"AU","bred_for":"Cattle herding, herding trials","breed_group":"Herding","life_span":"12 - 14 years","temperament":"Cautious, Energetic, Loyal, Obedient, Protective, Brave"}],"id":"9AXHhr6LG","url":"https://cdn2.thedogapi.com/images/9AXHhr6LG.jpg","width":1080,"height":1080}]
< undefined
> console.log(JSON.stringify(data, null, 4));
< VM319:1 [
    {
        "breeds": [
            {
                "weight": {
                    "imperial": "44 - 62",
                    "metric": "20 - 28"
                },
                "height": {
                    "imperial": "17 - 20",
                    "metric": "43 - 51"
                },
                "id": 21,
                "name": "Australian Cattle Dog",
                "country_code": "AU",
                "bred_for": "Cattle herding, herding trials",
                "breed_group": "Herding",
                "life_span": "12 - 14 years",
                "temperament": "Cautious, Energetic, Loyal, Obedient, Protective, Brave"
            }
        ],
        "id": "9AXHhr6LG",
        "url": "https://cdn2.thedogapi.com/images/9AXHhr6LG.jpg",
        "width": 1080,
        "height": 1080
    }
]
< undefined

По этому адресу возвращаются данные JSON, что означает нотация объектов JavaScript.

Помните основные типы из урока 1?

Любые данные, полученные из базовых типов, являются допустимым объектом JSON. Приведенные выше данные выглядят как массив объектов. У каждого объекта есть следующие поля: breeds / id / url / width / height. Нас интересует URL-адрес, доступ к которому можно получить следующим образом:

> data[0].url
< "https://cdn2.thedogapi.com/images/9AXHhr6LG.jpg"

Мы приближаемся! Нам нужна встроенная функция, которая будет выполнять веб-запрос, и когда он вернется, мы можем использовать указанную выше строку для получения строкового значения url.

Загрузить любой веб-сайт / конечную точку Api с помощью fetch ()

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

> fetch('https://api.thedogapi.com/v1/images/search')
< Promise {<pending>}
> await fetch('https://api.thedogapi.com/v1/images/search')
< Response {type: "cors", url: "https://api.thedogapi.com/v1/images/search", redirected: false, status: 200, ok: true, …}
> (await fetch('https://api.thedogapi.com/v1/images/search')).text()
< Promise {<pending>}
> await (await fetch('https://api.thedogapi.com/v1/images/search')).text()
< "[{"breeds":[{"weight":{"imperial":"23 - 28","metric":"10 - 13"},"height":{"imperial":"15.5 - 20","metric":"39 - 51"},"id":111,"name":"Finnish Spitz","bred_for":"Hunting birds, small mammals","breed_group":"Non-Sporting","life_span":"12 - 15 years","temperament":"Playful, Loyal, Independent, Intelligent, Happy, Vocal"}],"id":"hYsMv3NQi","url":"https://cdn2.thedogapi.com/images/hYsMv3NQi.jpg","width":630,"height":423}]"

Когда мы запускаем выборку с веб-адресом, он возвращает объект Promise. Promise - это базовый тип данных в JavaScript. Когда вы видите возвращаемое обещание, вы можете использовать оператор «await» перед ним, чтобы перейти к фактическому возвращаемому значению.

Когда мы ожидаем получения (https://api.thedogapi.com/v1/images/search), мы в конечном итоге получаем объект Response. На первый взгляд кажется, что статус - 200, а поле "ok" - true.

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

У объекта ответа есть метод члена класса, называемый text (). Когда мы вызываем text (), мы получаем еще одно обещание. Нет проблем, давайте воспользуемся еще одним словом «ожидание». Возвращается строка, содержащая данные JSON, которые нам небезразличны, это хороший прогресс.

Мы можем попытаться преобразовать JSON в строковой форме в объекты JSON (в данном случае массив). Обычно это делается с помощью встроенной функции JSON.parse (). Но если вы прочитаете документацию по fetch, окажется, что есть еще один удобный метод под названием json (), который можно использовать следующим образом:

> var data = await fetch('https://api.thedogapi.com/v1/images/search').then(result => result.json())
< undefined
> data[0].url
< "https://cdn2.thedogapi.com/images/x-LJYrq37.jpg"

Сначала мы вызываем fetch (https://api.thedogapi.com/v1/images/search) », чтобы получить обещание.

Затем мы вызываем .then () для объекта Promise. Эта функция-член принимает обратный вызов.

Обратный звонок принимает такую ​​форму:

inputVariable => (step1;step2;step3; return value)
or
(inputVariable) => {
   step1;
   step2;
   step3;
   ...
   return value;
}

О, правильно, обратные вызовы - это просто функции, без имен! Также вместо ключевого слова функции мы пишем = ›

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

В целом, у нас есть такая функция:

function getDogImageUrl() {
    const result = await fetch('https://api.thedogapi.com/v1/images/search').then(result => result.json())
    return result[0].url;
}
VM917:2 Uncaught SyntaxError: await is only valid in async function

Ха ... мы хотим использовать ожидание в обещании, но Chrome сообщает нам, что оператор await может использоваться только внутри async функций.

Хорошо, попробуем следующее:

async function getDogImageUrl() {
    const result = await fetch('https://api.thedogapi.com/v1/images/search').then(result => result.json())
    return result[0].url;
}

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

Создание изображений

Когда браузер загружает какие-либо страницы с сервера, он преобразует данные текстовой страницы в объекты JavaScript и отображает их на экране. Если мы погуглим, как делать изображения, мы быстро натолкнемся на эту страницу:



Что говорит нам, как создавать изображения:

var myImage = new Image(100, 200);
myImage.src = 'picture.jpg';
document.body.appendChild(myImage);

Этот фрагмент кода создает объект изображения с шириной = 100 и высотой = 200, устанавливает его src как «picture.jpg» и добавляет его в конец тела документа.

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

"https://cdn2.thedogapi.com/images/x-LJYrq37.jpg"

Итак, мы пробуем:

var myImage = new Image(100, 100);
myImage.src = "https://cdn2.thedogapi.com/images/x-LJYrq37.jpg";
document.body.appendChild(myImage);

И это изображение собаки появилось здесь, вы должны прокрутить вниз, чтобы увидеть их:

Мы можем упаковать этот фрагмент кода в функцию:

function makeImage(url) {
    var myImage = new Image(150, 150);
    myImage.src = url;
    return myImage;
}

Собираем оба вместе

У нас есть все необходимые компоненты. Соберем это вместе:

async function makePhotoCollage() {
     for (var i = 0; i < 50; ++i ) {
         const url = await getDogImageUrl();
         const image = makeImage(url);
         document.body.insertBefore(image, document.body.firstChild);
     }
}

Во-первых, нам нужно использовать ключевое слово async для этой внешней функции из-за вызова getDogImageUrl () внутри.

Во-вторых, вместо того, чтобы помещать изображения собак в конце документа, мы хотим, чтобы они отображались в самом верху. Итак, мы используем метод insertBefore документа document.body и помещаем наш объект изображения перед самым первым дочерним элементом.

Готовы к собакам? вызовите makePhotoCollage ()

Но подождите, а как насчет того, чтобы заставить их сказать «Гав!» когда мы нажимаем на них?

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

function makeImage(url, onClick) {
    var myImage = new Image(150, 150);
    myImage.src = url;
    myImage.addEventListener('click', onClick);
    return myImage;
}

async function makePhotoCollage() {
     for (var i = 0; i < 50; ++i ) {
         const url = await getDogImageUrl();
         const image = makeImage(url, () => { alert('Woof!'); } );
         document.body.insertBefore(image, document.body.firstChild);
     }
}

В makeImage () мы берем вторую входную переменную onClick.

onClick - это функция / обратный вызов.

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

  1. Тип события = «клик»
  2. Обработчик событий = onClick

В makePhotoCollage () мы создаем обратный вызов, который отправляет предупреждение со строкой «Woof!», И отправляем его в функцию makeImage.

Снова запустите makePhotoCollage () и попробуйте щелкнуть по одной из ваших собак.

Вот и все, что нужно!

Большая идея, лежащая в основе этих концепций

Итак, в чем дело?

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

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

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

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

Мы всего в паре уроков от взаимодействия со всем Интернетом и прохождения этого интервью!

В следующей статье: мы рассмотрим запуск JavaScript вне браузера / Выполнение вызовов на наш собственный сервер!
Спасибо за чтение.