www.machinelearningmastery.ru

Машинное обучение, нейронные сети, искусственный интеллект
Header decor

Home

JavaScript Async / Await: вход и выход

Дата публикации Oct 3, 2019

JavaScript - это однопоточный язык. Он выполняет код синхронно один за другим. Это означает, что JavaScript имеет один стек вызовов. Примером синхронного кода в javaScript являетсяоповещение

alert ("I am running");

Когда этот фрагмент кода выполняется, окно останавливается до тех пор, пока вы не отклоните предупреждение. Но это может быть проблемой при выполнении ajax-вызовов, прослушивателей событий, setTimeout и т. Д. Итак, как же JavaScript может быть асинхронным?

Ну вот гдеобратные вызовыприйти на помощь.

Callbacks

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

const welcome = (name)=> {
document.write("Welcome to this world " + name);
}const beMyGuest = (callback)=> {
let name = prompt("May I know your name?");
callback(name);
}beMyGuest(welcome);

Из приведенного выше примера обратные вызовы кажутся простыми и делают код чистым. Практический пример обратных вызовов - при выполнении вызова API. Мы передаем обратные вызовы для выполнения, когда ответ доступен. Рассмотрим следующий сценарий

const getProfile = (id) => {
$.ajax({
url: `demo_test.txt/${id}`,
success: (result) => {
let name = result.name;
$.ajax({
url: `demo_test.txt/${name}`,
success: (address) => {
let city = address.cityName;
$.ajax({
url: `demo_test.txt/${city}`,
success: (phone) => {
...
},
error: (err) => console.log(err)
});
},
error: (err) => console.log(err)
});
},
error: (err) => console.log(err);
});
}

В приведенном выше примере каждый запрос API зависит от результата предыдущего запроса. Это вложение обратных вызовов продолжает увеличиваться, если зависимость увеличивается и достигает точки, где невозможно отслеживать выполнение кода. Код становится нечитаемым и почти невозможным для отладки. Это называетсяCallback HellилиПирамида Судьбы.Чтобы преодолеть эту проблему,Promises были введены.

обещания

Обещания - это объекты, представляющие асинхронные операции, которые всегда в конечном итоге возвращают значение либо успеха, либо неудачи. Обещание имеет три состояния:

  • в ожидании
  • решены
  • отвергнуто
const goToSleep = () => {
return new Promise((resolve, reject) => {
setTimeout(()=>{
let error = false;
if(!error){
resolve({text: "Ready for bed"});
} else {
reject();
}
},1000)
})
}
goToSleep().then(status => {
console.log(status.text);
});

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

const getProfile = (id) => {
fetch(`demo_test.txt/${id}`)
.then(res => res.json())
.then(response => {
fetch(`demo_test.txt/${response.name}`)
.then(res => res.json())
.then(response => {
fetch(`demo_test.txt/${response.city}`)
.then(res => res.json())
.then(response => {
...
})
.catch (err => console.log(err))
})
.catch(err => console.log(err))
})
.catch(err => console.log(err));
}

Как мы видим выше, Promises предоставляет нам преимущество читабельности кода, лучшей обработки ошибок, лучшего способа определения потока управления кодом и меньшей связности. Можно подумать, что проблему глубоко вложенных обратных вызовов можно избежать, зацикливаясь на массиве, который возвращает Promises, а затем сохраняет результат в объекте или массиве. Цикл остановится, когда обещания будут выполнены. Но нет события, определяющего ‘сделанный'в JavaScript из-за его асинхронной природы, чтобы остановить цикл. Чтобы избежать этой проблемы, можно использоватьPromise.all()но у него есть своя оговорка. Если одно Обещание не выполняется, все Обещания не выполняются!

Кроме того, обработка ошибок во вложенных Promises похожа на поиск булавки в стеке сена! Довольно сложно выяснить, какие Обещания столкнулись с ошибкой или были отклонены.

Асинхронный / Await

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

«Функция async / await объявляет асинхронную функцию, которая будет возвращать объект« AsyncFunction ».»

Он использует цикл событий JavaScript для асинхронной работы, используя «Promise» для возврата своих результатов. Async / await больше похож на синтаксический сахар для «обещаний».

/**simple async/await example*/function returnAfter5Secs() {
return new Promise(resolve => {
setTimeout(() => {
resolve(‘resolved Promise’);
}, 5000)
})
}async function asyncFuncCall() {
console.log(‘async calling’);
let result = await returnAfter5Secs();
console.log(result);
}asyncFuncCall();

СИНТАКСИС

async function fnName (params) {   //...statements}

* имя → название функции

* params → имя аргументов для передачи в функцию

* операторы → операторы, составляющие тело функции

* возвращаемое значение → обещание, которое будет разрешено со значением, возвращаемым из асинхронной функции или отклоненным с необработанным исключением из асинхронной функции

Давайте углубимся в ...

Асинхронная функция может содержатьawait выражение, которое приостанавливает выполнение асинхронной функции для ожидания разрешения переданного «обещания». Как только «Обещание» разрешено, асинхронная функция возобновляет выполнение и оценивает значение разрешенного обещания.

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

Асинхронные / ожидающие функции призваны упростить реализацию обещаний достижения синхронного кода. Подобно тому, как обещания являются структурированными обратными вызовами, так же async / await походит на объединение генераторов и обещаний.

Давайте посмотрим на другой пример использования async / await вместе

async function foo(){
let promise = new Promise((resolve, reject)=>{
setTimeout(()=>{
resolve(‘i am ready’);
}, 1000)
});
let result = await promise;
alert(result);
}foo();

Теперь давайте вернемся за кулисы и посмотрим, как async / await фактически выполняет то, что делает. Для этого мы попробуем написать асинхронную функцию с нуля. Мы сделаем это, используяГенераторы,Наша цель - написать асинхронную функцию, которая принимает генератор в качестве параметра, а затем мы используем операторы yield для получения результата, аналогичного «await».

async(function* () {
const res = yield fetch(‘https://jsonblob.com/api/c478ebb2-dba0- 11e9-8 cbd-53f0f6dae08d’);
const result = yield res.json();
console.log(result);
});

Подожди! Это точно так же, как операторы await в приведенных выше примерах.awaitзаявления ничегоyield заявления Async / await - это просто абстракциягенераторыа такжеyield заявления.

Для создания экземпляра генератора в приведенном выше примере нам нужноасинхронной«pollyfill», Мы будем вкладывать «следующее» значение рекурсивно для каждогоyield внутри своего обещанияthen обратный звонок доdone правда.

async = generator => {
const gen = generator();
(function next(val) {
const result = gen.next(val);
if (result.done) return;
result.val.then(next);
}());
}

Итак, что мы видим выше, так это то, что async / await является просто генераторами и выдает операторы, которые помогают приостановить выполнение. В качестве альтернативы мы можем сказать, что асинхронные функции дают нам возможность присваивать разрешенное значение Promise переменной, получая доступ к этому значению, даже если Promise окружен функцией обратного вызова.

Вывод

Подводить итоги . , , ,

  1. В JavaScript теперь есть что-то, называемое асинхронными функциями. Они определяются путем добавления слова «async» перед именем функции в определении функции, например:
(async function () {
try {
await doSomeWork();
} catch (err) {
console.log(err);
}
})();

2. Код внутри асинхронной функции можно заставить ждать результат, используя оператор «await».

3. Оператор await возвращает результат асинхронной функции, когда ее выполнение завершено.

4. Оператор await нельзя использовать где-либо за пределами асинхронной функции.

5. Если асинхронные функции генерируют какие-либо ошибки / исключения, они всплывают до родительского, как и ожидалось в JavaScript. Если мы не поймаем исключение, код молча завершится неудачей. Чтобы избежать этого, нам нужно обернуть код async / await внутри блока try / catch

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

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

Удачного кодирования ... !!!

Оригинальная статья

Footer decor

© www.machinelearningmastery.ru | Ссылки на оригиналы и авторов сохранены. | map