| title | Занятие 4.2 |
|---|---|
| description | Базовое использование API и JavaScript. Как работать с сетевыми ресурсами |
Подробнее будет в третьем модуле на занятии про асинхронный код
- Отрисовка DOM
- Обработка пользовательского ввода
- Выполнение JS кода
- Среда выполнения содержит очередь событий (список событий, подлежащих обработке)
- Каждое событие ассоциируется с некоторой функцией.
- Каждый вызов функции добавляет запись в стек
- При завершении функции запись изымается из стека
- Когда стек освобождается, событие извлекается из очереди и обрабатывается (функция вызывается).
На бытовом уровне мы могли бы это объяснить так...
Поэтому операции, которые занимают длительное (больше 50 ms) операции стараются
- переложить на внешнего исполнителя
- отложить исполнение и разбить на части
Так появляется асинхронный код - когда результат вы получаете не немедленно, а отложено во времени.
Как работать с таким асинхронным кодом? Как это выглядит?
// работа с callback-функциями
const x = 2;
// результат мы можем обработать в callback-функции
calculateSomethingAsyncWithCallback(x, (result) => {
console.log(result);
});
// в node.js было принято
calculateSomethingAsyncWithCallback(x, (error, result) => {
if (error) {
return console.error(error);
}
// ...
});// работа с callback-функциями
const x = 2;
calculateSomethingAsyncWithCallback(x, (result) => {
calculateSomethingElseAsyncWithCallback(result, (secondResult) => {
console.log(result);
});
});Для решения проблемы callback hell ввели интерфейс Promise.
function doSomething() {
return new Promise((resolve, reject) => {
console.log("Готово.");
// Успех в половине случаев.
if (Math.random() > 0.5) {
resolve("Успех");
} else {
reject("Ошибка");
}
});
}
const promise = doSomething();
promise.then(successCallback, failureCallback);
promise.then(successCallback).catch(failureCallback);calculateSomethingAsyncWithPromise(x)
.then((result) => calculateSomethingElseAsyncWithPromise(result))
.then((secondResult) => console.log(secondResult));Но в Javascript приходит все больше и больше людей с других языков, и им непривычно читать такой код. Кроме того он имеет некоторые проблемы (например нам нужен одновременный доступ к result и secondResult).
Появились async функции. Которые предоставляют await механизм.
Мы можем пометить функцию ключевым словом async. Это дает следующее:
-
функция теперь неявно возвращает Promise
-
внутри функции мы можем использовать ключевое слово
awaitдля разворачивания Promise-результатов
(async function () {
const x = 2;
const result = await calculateSomethingAsyncWithPromise(x);
const secondResult = await calculateSomethingElseAsyncWithPromise(result);
console.log(secondResult);
})();const x = 2;
const result = await calculateSomethingAsyncWithPromise(x);
const secondResult = await calculateSomethingElseAsyncWithPromise(result);
console.log(secondResult);Краткий итог:
- некоторый функции нужно вызывать с ключевым словом
await awaitработает только внутри функций, которые помечены какasyncи в top-level
Подробнее мы будем разбирать на занятии про асинхронность
И еще одно отступление про асинхронность (мы будем об этом говорить подробнее на занятии по дизайну вашего API)
В разработке принято писать на уровне интерфейсов (абстракций), а не реализаций. То есть вы должны знать ЧТО делает функция или модуль, но не КАК.
Когда вы начинаете использовать детали реализации - это называется "протекающая абстракция".
Типичные кандидаты на асинхронные операции:
- запрос данных от пользователя
- сохранение и чтение данных
- обращение к стороннему сервису
- валидации и сложные вычисления
Но при этом
- для запроса данных от пользователя есть синхронные
alert/prompt - для чтения и сохранения данных есть синхронный
localStorage
Лучше сразу заложить возможность для расширения, и использовать асинхронные обертки. Тогда в любой момент можно будет поменять реализацию, и вместо localStorage сохранять данные на сервере, например. А вместо alert показывать красивое стилизованное модальное окно (которое не блокирует поток).
async function asyncPrompt(request) {
return prompt(request);
}
// const x = asyncPrompt(); работать не будет
const x = await asyncPrompt();Для работы с HTTP запросами у нас есть два варианта (на самом деле больше, если подключать библиотеки):
fetch - поддерживается современными браузерами, предоставляет Promise-based интерфейс (удобен для async функций) и прост в использовании.
// await-friendly окружение
let response = await fetch(url);
let text = await response.text();
console.log(text);// await-friendly окружение
let response = await fetch("/article/fetch/post/user", {
method: "POST",
headers: {
"Content-Type": "application/json;charset=utf-8",
},
body: JSON.stringify(user),
});
let jsonData = await response.json();
console.log(jsonData);fetch возвращает вам объект типа Response.
Чаще всего используются
- поле
ok - поле
status - методы
text()иjson()
Дополнительное задание:
при заходе на страницу показать пользователю погоду в его городе. Для получения этой информации можно сделать запрос на https://get.geojs.io/v1/ip/geo.json, который вернет данные в формате JSON.
Если вы хотите собрать все вместе, можете выполнить следующий проект (его уже можно показывать друзьям).
Само домашнее задание у вас будет позже, но уже сейчас вы можете выполнять часть, связанную со страницей.
- Путеводитель по JavaScript Promise для новичков
- Public APIs
- JavaScript. Как работать с API Telegram, Youtube и VK
- Что на самом деле происходит, когда пользователь вбивает в браузер адрес google.com
-
Что такое CORS?
-
Что такое и какие есть коды ответов HTTP?
-
Что такое jsonp-запрос?
-
Быть в состоянии рассказать что такое XHR, AJAX, CDN
-
Чем XMLHTTPRequest отличается от fetch?