# Async JS

## Главное

Как это использовать в старых браузерах: <https://babeljs.io/>

## Синхронный JS

```javascript
function hello() { return "Hello" };
hello();
```

## Асинхронный JS

### Async/Await

#### Async

```javascript
// ex1
async function hello() { return "Hello" };
hello();

// ex2
let hello = async function() { return "Hello" }; // возвращает promise
hello();

// ex3 — то же, что и ex2, но через стрелочные функции
let hello = async () => { return "Hello" };
hello();

// ex1, ex2, ex3 делают одно и то же

// Чтобы получить значение, которое возвращает Promise, 
// мы как обычно можем использовать метод .then():
hello().then((value) => console.log(value))
// или еще короче
hello().then(console.log)

```

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

#### Await

Асинхронные функции становятся по настоящему мощными, когда вы используете ключевое слово [await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await)  — по факту, **`await` работает только в асинхронных функциях**. Мы можем использовать await перед promise-based функцией, чтобы остановить поток выполнения и дождаться результата ее выполнения (результат Promise). В то же время, остальной код нашего приложения не блокируется и продолжает работать.

Вы можете использовать `await` перед любой функцией, что возвращает Promise, включая Browser API функции.

Небольшой пример:

```javascript
async function hello() {
  return greeting = await Promise.resolve("Hello");
};

hello().then(alert);
```

### Promises

[`Promise`](https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Promise) (промис, англ. "обещание") - это объект, представляющий результат успешного или неудачного завершения асинхронной операции. Так как большинство людей пользуются уже созданными промисами, это руководство начнем с объяснения использования вернувшихся промисов до объяснения принципов создания.&#x20;

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

```javascript
function doSomething() {
  return new Promise((resolve, reject) => {
    console.log("Готово.");
    // Успех в половине случаев.
    if (Math.random() > .5) {
      resolve("Успех")
    } else {
      reject("Ошибка")
    }
  })
}

doSomething().then(successCallback, failureCallback);
```

Обработка ошибок Promise:

```javascript
function errorHandler(someError) {}

doSomething()
    .then(successCallback, failureCallback)
    .catch(errorHandler);

или

doSomething()
    .then(successCallback, failureCallback)
    .catch((error) => {...});
```

### Примеры

#### Переписываем Promises с ипользованием async/await

Давайте посмотрим на пример из предыдущей статьи:

```javascript
fetch('coffee.jpg')
.then(response => {
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  } else {
    return response.blob();
  }
})
.then(myBlob => {
  let objectURL = URL.createObjectURL(myBlob);
  let image = document.createElement('img');
  image.src = objectURL;
  document.body.appendChild(image);
})
.catch(e => {
  console.log('There has been a problem with your fetch operation: ' + e.message);
});
```

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

```javascript
async function myFetch() {
  let response = await fetch('coffee.jpg');

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  } else {
    let myBlob = await response.blob();

    let objectURL = URL.createObjectURL(myBlob);
    let image = document.createElement('img');
    image.src = objectURL;
    document.body.appendChild(image);
  }
}

myFetch()
.catch(e => {
  console.log('There has been a problem with your fetch operation: ' + e.message);
});
```

Согласитесь, что код стал короче и понятнее — больше никаких блоков `.then()` по всему скрипту!

Так как ключевое слово `async` заставляет функцию вернуть Promise, мы можем использовать гибридный подход:

```javascript
async function myFetch() {
  let response = await fetch('coffee.jpg');
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  } else {
    return await response.blob();
  }
}

myFetch().then((blob) => {
  let objectURL = URL.createObjectURL(blob);
  let image = document.createElement('img');
  image.src = objectURL;
  document.body.appendChild(image);
}).catch(e => console.log(e));
```

#### Await и Promise.all()

```javascript
async function fetchAndDecode(url, type) {
  let response = await fetch(url);

  let content;

  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  } else {
    if(type === 'blob') {
      content = await response.blob();
    } else if(type === 'text') {
      content = await response.text();
    }

    return content;
  }

}

async function displayContent() {
  let coffee = fetchAndDecode('coffee.jpg', 'blob');
  let tea = fetchAndDecode('tea.jpg', 'blob');
  let description = fetchAndDecode('description.txt', 'text');

  let values = await Promise.all([coffee, tea, description]);

  let objectURL1 = URL.createObjectURL(values[0]);
  let objectURL2 = URL.createObjectURL(values[1]);
  let descText = values[2];

  let image1 = document.createElement('img');
  let image2 = document.createElement('img');
  image1.src = objectURL1;
  image2.src = objectURL2;
  document.body.appendChild(image1);
  document.body.appendChild(image2);

  let para = document.createElement('p');
  para.textContent = descText;
  document.body.appendChild(para);
}

displayContent()
.catch((e) =>
  console.log(e)
);
```

Фишка в вызове Promise.all — дожидаемся выполнения всего кода


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://appsecurity.gitbook.io/devops/ppc/ppc-langs/frontend/js-ts/javascript/async-js.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
