От «Шоссе в (обратный) ад» к «Лестнице в (асинхронный/ожидание) рай»
Здравствуйте, я вернулся, чтобы немного поговорить о JavaScript. На этот раз я покажу, как JavaScript изменил свой способ работы с асинхронным кодом. Итак… приступим!!!
Обратные вызовы
(Не так уж) давно, когда нам нужно было работать с асинхронным кодом, мы использовали обратные вызовы, в то время, когда это было лучше всего, это было похоже на волшебство, мы создавали функции, которые выполнялись после того, как что-то было готово, ЭТО ЗАМЕЧАТЕЛЬНО не так ли?
NO!!!!
Я не скажу, что это самое худшее в мире, в то время это было здорово, но через какое-то время наш код уже не был таким красивым, и мы чувствовали себя как в аду! Давайте посмотрим на простой пример того, о чем я говорю. Давайте воспользуемся PokeAPI, чтобы получить некоторую информацию. Нам нужно сделать четыре запроса:
- Сначала информация о покемонах: http://pokeapi.co/api/v2/pokemon/1
- Во-вторых, мы сделаем запрос, чтобы получить информацию о его первом ходе.
- В-третьих, мы сделаем запрос, чтобы получить информацию о движущейся машине.
- В-четвертых, мы сделаем запрос на получение информации об элементе машины.
(function () { const API_BASE_URL = 'https://pokeapi.co/api/v2'; let pokemonInfo = null; let moveInfo = null; let machineInfo = null; let itemInfo = null; const pokemonXHR = new XMLHttpRequest(); pokemonXHR.responseType = 'json'; pokemonXHR.open('GET', `${API_BASE_URL}/pokemon/1`); pokemonXHR.send(); pokemonXHR.onload = function () { pokemonInfo = this.response const moveXHR = new XMLHttpRequest(); moveXHR.responseType = 'json'; moveXHR.open('GET', pokemonInfo.moves[0].move.url); moveXHR.send(); moveXHR.onload = function () { moveInfo = this.response; const machineXHR = new XMLHttpRequest(); machineXHR.responseType = 'json'; machineXHR.open('GET', moveInfo.machines[0].machine.url); machineXHR.send(); machineXHR.onload = function () { machineInfo = this.response; const itemXHR = new XMLHttpRequest(); itemXHR.responseType = 'json'; itemXHR.open('GET', machineInfo.item.url); itemXHR.send(); itemXHR.onload = function () { itemInfo = this.response; console.log('Pokemon', pokemonInfo); console.log('Move', moveInfo); console.log('Machine', machineInfo); console.log('Item', itemInfo); } } } } })();
Как видите, это очень простой код, но он уже запутан большим количеством обратных вызовов. Теперь представьте эту ситуацию в крупномасштабном приложении… Разве это не то, что мы хотим поддерживать в течение длительного времени, верно?
Обещания
У обратных вызовов было свое время славы, но после множества адов обратных вызовов появился луч надежды: обещания, они пришли, чтобы решить наши проблемы с (обратным) адом. Таким образом, тот же код выше, использующий промисы, будет выглядеть примерно так:
(function () { const API_BASE_URL = 'https://pokeapi.co/api/v2'; let pokemonInfo = null; let moveInfo = null; let machineInfo = null; let itemInfo = null; const showResults = () => { console.log('Pokemon', pokemonInfo); console.log('Move', moveInfo); console.log('Machine', machineInfo); console.log('Item', itemInfo); }; const getItemInfo = response => { itemInfo = response; showResults(); }; const getMachineInfo = response => { machineInfo = response; fetch(machineInfo.item.url) .then(res => res.json()) .then(getItemInfo) .catch(err => console.log(err)); }; const getMoveInfo = response => { moveInfo = response; fetch(moveInfo.machines[0].machine.url) .then(res => res.json()) .then(getMachineInfo) .catch(err => console.log(err)); }; const getPokemonInfo = response => { pokemonInfo = response; fetch(pokemonInfo.moves[0].move.url) .then(res => res.json()) .then(getMoveInfo) .catch(err => console.log(err)); }; fetch(`${API_BASE_URL}/pokemon/1`) .then(res => res.json()) .then(getPokemonInfo) .catch(err => console.log(err)); })();
Как видите, визуально код выглядит намного лучше, когда мы используем промисы, и это всего лишь простой пример (и не использование реальной силы промисов), он просто показывает разницу в написанном коде. Теперь нам больше не нужно беспокоиться об Callback Hell, но мы все еще можем улучшить наш код.
асинхронно/ожидание
С промисами наш код намного красивее, чем раньше, когда мы использовали обратные вызовы, но код мог бы быть немного проще, мы могли бы написать меньше кода и сделать код еще лучше визуально. Мы можем сделать это, используя функцию async/await. Давайте посмотрим, как это работает:
const axios = require('axios'); const API_BASE_URL = 'https://pokeapi.co/api/v2'; let pokemonInfo; let moveInfo; let machineInfo; let itemInfo; function showResults () { return new Promise(resolve => { setTimeout(() => { console.log('Pokemon', pokemonInfo.data); console.log('Move', moveInfo.data); console.log('Machine', machineInfo.data); console.log('Item', itemInfo.data); resolve('Finished!!!'); }, 2000); }); } async function init () { try { pokemonInfo = await axios(`${API_BASE_URL}/pokemon/1`); moveInfo = await axios(pokemonInfo.data.moves[0].move.url); machineInfo = await axios(moveInfo.data.machines[0].machine.url); itemInfo = await axios(machineInfo.data.item.url); console.log('Building results report...'); const message = await showResults(); console.log(message); } catch (error) { console.log('ERROR', error); } } init();
Посмотрите на приведенный выше код… Это УДИВИТЕЛЬНО!!! Мы написали всего несколько строк кода и сделали больше, чем с кодами, которые я показывал ранее, и код намного чище, чем другие!!!
Вывод
Вот и все, я просто хотел показать вам, ребята, путь, который мы все прошли, чтобы добраться туда, где мы сейчас находимся… JavaScript — удивительный язык, и он всегда становится лучше благодаря новым удивительным функциям, и мы должны остановиться на мгновение, чтобы прочитать об этих функциях. и начните использовать их для улучшения нашего кода, нашей производительности и наших продуктов и услуг!
Я надеюсь, что вам понравилась эта статья и что она может быть вам полезна! Пока и до встречи в следующей статье!!! :D