Когда ES6 захватил планету, пришло время всем либо узнать об Async - Await, либо провести свою жизнь в аду обратных вызовов.

Полагаю, вы знаете обещания. Если нет, прочтите этот блог. Он охватывает все основы, а затем вернемся сюда. Начнем с основ Async Await.

Мы не хотим сложных вещей в жизни. Асинхронные вещи - исключение, поскольку мы хотим использовать их возможности. Обещания были отличным способом сделать асинхронную задачу более читаемой, чем обратные вызовы с их нотациями then и catch. Async Await еще чище и интуитивно понятнее, чем это.

const add10 = (num) => {
  return num + 10
}
console.log(add10(5)) // 15
const add5 = async (num) => num + 5;
console.log(add5(5)) // Promise {<resolved>: 10}

Единственное различие между двумя вышеуказанными функциями - это ключевое слово async. Async оборачивает возвращаемое значение в обещание. Другой пример:

const processDataAsycn = async (num) => {  
   if(typeof num === 'number') {  
     return 2*num;  
   } else {  
     throw new Error('Something went wrong');  
   }  
 };  
 processDataAsycn(21).then((data) => {  
   console.log('Data from processDataAsycn() with async( When promise gets resolved ): ' + data);  
 }).catch((error) => {  
   console.log('Error from processDataAsycn() with async( When promise gets rejected ): ' + error);  
 });

А теперь давайте подождем -

  • работает только с функцией с добавлением async (асинхронные функции)
// async function body continues ...
let value = await promise;

Ключевое слово await заставляет JavaScript ждать, пока это обещание не исполнится, и возвращает результат.

В приведенном выше случае возвращаемое значение 8 приходит через 4 секунды.

Давайте посмотрим на пример цепочки обещаний.

fetch('/article/promise-chaining/user.json')
  .then(user => fetch(`https://api.github.com/users/${user.name}`))
  .then(response => response.json())
  .then(githubUser => new Promise(function(resolve, reject) {
    let img = document.createElement('img');
    img.src = githubUser.avatar_url;
    img.className = "promise-avatar-example";
    document.body.append(img);

    setTimeout(() => {
      img.remove();
      resolve(githubUser);
    }, 3000);
  }))
  // triggers after 3 seconds
  .then(githubUser => alert(`Finished showing ${githubUser.name}`));

Преобразование вышеуказанного в пример async await:

Это делает код чистым. То, что происходит в точности, совпадает с тем, что происходит в обещании. Он входит только тогда, когда обещание выполнено. Точно так же выполнение кода останавливается при ожидании. Технически это не остановлено, так как другие вещи могут использовать процессор до тех пор, пока это обещание не будет выполнено. Таким образом, все, что находится ниже, не обрабатывается, пока не будет разрешено обещание.

Ошибка

Допустим, обещание ожидания отклонено. Тогда упаковка обещания, выполненная с помощью async, также приведет к отклоненному обещанию, если это обещание await отклонено не обработано в try … catch.

async function f() {

  try {
    let response = await fetch('http://no-such-url');
  } catch(err) {
    alert(err); // TypeError: failed to fetch
  }
}

f(); // f() returns a resolved promise but if we remove try catch, it will result in rejected promise

Отличное чтение и многое другое можно найти здесь на async await здесь

Как async await спас меня в ответ на решение проблемы при тестировании -

Проблема: нужно протестировать компонент. Компонент вызывает внутреннюю функцию в componentDidMount.. Существует импортированный модуль, который выполняет вызов API и возвращает обещание. Внутренняя функция использует этот импортированный модуль API и устанавливает состояние при разрешении обещания и делает что-то еще при отклонении обещания.

Неизвестные:

  1. Как смоделировать внешний импортированный модуль с помощью jest / энзима?
  2. В тестах: как дождаться разрешения обещания, а затем проверить состояние?

Решение:

Отличное чтение для поиска решения 1-го:

Теперь в тестах:

Проблема в том, что мне нужно подождать, пока не вернется фиктивный вызов. Этот компонент монтировался как асинхронная задача, и мне нужно утверждать только тогда, когда фиктивное обещание разрешено.

Решения:

Код класса React для указанной выше проблемы находится чуть выше, а решение ниже.

Что происходит в решении?

Мы используем заглушку sinon, чтобы заменить это всякий раз, когда вызывается функция выборки, заменять ее на

function() { return Promise.resolve(mockData)}

Поэтому, когда мы монтируем компонент в строке 5, также вызывается это обещание. Затем в результате этого вызывается строка 7. Хотя это хакерство (я думаю), на данный момент нет возможности использовать это преимущество состояния гонки.

Я использую по-другому,

Я не знаю, почему это работает, так как я не могу получить возвратный тип крепления. Но пока обещание не разрешено для componentDidMount, это выполнение остается в ожидании. Кто-нибудь знает, как это работает - прокомментируйте, пожалуйста, в блоге.

Купи мне кофе, хлопнув по почте. На каждые 10 хлопков я дарю себе кофе. Вы можете связаться со мной по адресу [email protected]