Почему JavaScript асинхронен?
JavaScript работает по принципу цикла событий. Это означает, что существует только один поток выполнения и весь язык асинхронен. Не существует понятия блокировки или синхронного потока кода.
Например:
line A line B line C line D
может быть выполнено как
line B -> line C -> line D -> line A
or
line D -> line A -> line B -> line A
Однако учтите, что это не случайно. Дело не в том, что JavaScript — сумасшедший. Нисколько. JavaScript — превосходный язык программирования, некоторые говорят, что даже лучший.
Это связано с циклом событий, который никогда не позволяет никому тратить время на ожидание того, что что-то произойдет.
Это что-то может быть:
- Сетевое событие
- I/O
- Обработка
- запрос к базе данных
- Чтение файлов
- Длинный опрос
Это может быть что угодно из этого и даже больше. Как виртуальная машина JavaScript может узнать, что занимает и сколько времени?
Чтобы бороться с этой реальностью, начинающие программисты используют так называемые обратные вызовы.
Это выглядит так.
function networkRead(a, b, cb) { findSomething(a,b); .... dosomething() { cb(); } } doatEnd() { console.log("Finished"); } networkRead(2, 3, doatEnd);
Поскольку в JavaScript функции имеют тот же статус, что и переменные, вы можете передавать их, как будто это ничего не значит. Вы видите проблему?
Это не только приводит к нечитаемому потоку кода, но и приводит к аду обратного вызова — термину, используемому многими разработчиками JS.
Что такое ад обратного вызова?
Ад обратного вызова происходит, когда функция A вызывает функцию B, которая вызывает C, и возврат или удаление стека вызовов функции происходит в обратном порядке.
Отступы становятся все глубже и глубже, и программист не понимает, что и когда происходит.
Определенно не идеальная ситуация. В таких языках, как C и Python, у вас будут циклы, вложенные глубоко внутри блоков с отступом, но тогда вы получите четкое представление о последовательности.
Даже в C вложенность в большинстве случаев не очень глубокая.
Что такое обещание?
Чтобы исправить это и многое другое, JavaScript придумал так называемый объект-промис из ES6 и более поздних версий. Промис — это особый вид объекта JavaScript, который позволяет вам писать такой код.
axios.get({ }).then(function() { console.log("HTTP get succeeded"); }).catch(function(err) { throw("error occurred" + err); });
Здесь вы видите, что сетевой ввод-вывод или HTTP GET, который определенно занимает больше времени, чем локальная обработка, можно было бы ожидать с использованием предложения then(), что значительно улучшает читаемость.
Но при этом простое использование блока then() не решит проблемы асинхронности в JavaScript. Спросите любого опытного программиста, и он скажет вам, почему.
Вы можете объединять обещания и делать с ними множество вещей. В наши дни в JavaScript также существует концепция async/await. Это выглядит так.
async function() { await longTask(); }
Это распространенный способ обойти асинхронную природу JavaScript. Я использовал оба варианта, но мне нравится подход с обещаниями. Что касается JavaScript, то в наши дни это действительно большой язык, в котором часто происходит множество улучшений.
Новые модули публикуются на npm, с node.js происходит множество инноваций; вам действительно следует следить за новейшим методом решения проблемы асинхронности в Js.
Почему они важны?
Спросите любого опытного разработчика JavaScript, и он скажет, что замыкания, обещания и даже простой цикл for() иногда могут сбить с толку разработчика. Вы никогда не сможете угадать, почему что-то происходит не по порядку.
Просто добавьте console.log() и убедитесь сами. Вы подумаете, почему, а затем автоматически научитесь, и после нескольких ответов на stackoverflow вы станете мудрее.
Использование промисов не решит всех ваших проблем, но в большинстве случаев сделает ваш код чище.
Вещи, на которые стоит обратить внимание
Обещание — это полезная концепция. То же самое относится и к закрытиям, которые являются еще одной областью, которая сбивает с толку новичков. Замыкание — это ограниченный блок, который выполняется с переменными, содержащимися в области видимости. Замыкания встречаются в Python как лямбда-функции.
Промис также можно отклонить, если по какой-то причине выполнение длинной задачи не удалось. Вам лучше убедиться, что случай ошибки обработан.
Кроме того, обещания не решат всех ваших проблем. Бывают случаи, когда все же необходимо использовать проверенную временем модель обратного вызова.
Вы можете попробовать использовать промисы. Если они не сработают, вы можете вернуться к обратным вызовам.
Помните, что JavaScript является однопоточным и основан на событиях. У него нет времени ждать вашей обработки. Если вы обнаружите, что используете устаревшие синхронные методы, вы без необходимости ухудшите производительность.
Заключение
Мы изучили мир объекта обещания JavaScript и его важность/роль в проектах JavaScript. Однако обещания не являются окончательным ответом на асинхронное кодирование и связанные с ним проблемы.
Это может помочь уменьшить количество обратных вызовов, которые вы бы использовали без него.