Узнайте историю использования async/await в JavaScript на примерах

В этой истории мы узнаем об истории async/await в JavaScript на примерах.

Фон:

Функция обратного вызова JavaScript

В JavaScript callback(), promises и async/await — это все три метода работы с асинхронными данными. Асинхронное программирование позволяет программам выполнять несколько задач одновременно, не дожидаясь завершения одной перед запуском другой. Между тем, в синхронном программировании вы ждете завершения одной задачи, прежде чем переходить к следующей.

До выпуска ES6, где promises были введены в JavaScript, долгое время использовались callback() функции. Промисы упрощают обработку асинхронных данных. ES7 представил async/await, который по-прежнему управляет промисами, но обрабатывает их красиво и синхронно.

Пример:

const personNames = [
  { firstName: 'David', lastName:'Smith' },
  { firstName: 'Andrew', lastName:'Tate' }
];

function getNames() {
  setTimeout(() => {
    let result = '';
    personNames.forEach((name, index) => {
      result += `<li>${name.firstName}</li>`;
    });
    document.body.innerHTML = result;
  }, 2000);
}

getNames(); // Call the function to get the output

В приведенном выше примере функция getNames() используется для извлечения и отображения имен людей, хранящихся в массиве personNames, после задержки в 2 секунды с использованием setTimeout(). После задержки в 2 секунды он загрузит два первых имени на экран.

Вывод:

Теперь добавим имя нового человека

function addName( name ) {
setTimeout(() => {
personNames.push(name);
}, 3000);
}
getNames( );
addName({ firstName: ‘Joe’, lastName:’Smith’ });

В этом случае мы не сможем увидеть имя третьего лица, потому что функция addName заняла больше времени, чем функция getNames. Когда getNames вызывается и сразу за ней следует функция addName, функция getNames() не ждет завершения выполнения функции addName() и возвращает результат только с первыми двумя именами в массиве personNames. В результате имя третьего лица не отображается. И результат будет тот же.

Вывод:

Вот где появляется концепция callback(), это один из способов справиться с этим.

обратный вызов()

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

Теперь попробуйте тот же пример с callback( ) и посмотрите, что получится:

const personNames = [
  { firstName: 'David', lastName:'Smith' },
  { firstName: 'Andrew', lastName:'Tate' }
];

function getNames() {
  setTimeout(() => {
    let result = '';
    personNames.forEach((name, index) => {
      result += `<li>${name.firstName}</li>`;
    });
    document.body.innerHTML = result;
  }, 2000);
}

Теперь давайте добавим имя нового человека, используя функцию callback( ).

function addName(name, callback) {
  setTimeout(() => {
    personNames.push(name);
    callback();
  }, 3000);
}

addName({ firstName: 'Joe', lastName:'Smith' }, getNames);

Выход:

После ожидания в течение пяти секунд в теле документа должен появиться неупорядоченный список «Дэвид», «Эндрю» и «Джо» в качестве имен каждого из трех человек.

В приведенном выше примере addName() принимает функциюcallback в качестве аргумента и вызывает ее после добавления нового имени в массивpersonNames. Вот как работаетcallback( ). Это работало, потому что приходилось ждать, пока функция создаст и добавит имя, прежде чем вызывать thecallback( )function.

Как сообщает W3schools:

Асинхронное программирование — это метод, который программы JavaScript могут использовать для выполнения длительных задач одновременно с другими процессами. Асинхронное программирование может быть сложным для написания и исправления.

Обратные вызовы редко используются в современных асинхронных подходах JavaScript.

Вместо этого для решения проблем асинхронного программирования JavaScript использует промисы.

Обещания

Обещания в JavaScript используются для управления асинхронными операциями. Обещания часто используются для задач, выполнение которых требует времени. Например, получение данных из API, чтение файла с сервера или выполнение трудоемкой операции.

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

Теперь попробуйте тот же пример с Promises и посмотрите, что получится:

const personNames = [
  { firstName: 'David', lastName:'Smith' },
  { firstName: 'Andrew', lastName:'Tate' }
];

function getNames() {
  setTimeout(() => {
    let result = '';
    personNames.forEach((name, index) => {
      result += `<li>${name.firstName}</li>`;
    });
    document.body.innerHTML = result;
  }, 2000);
}

function addName(name) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      personNames.push(name);

      // to resolve
      const error = false; // first check errors
      if (!error) {
        resolve();
      } else {
        reject('Error: Something went wrong!');
      }
    }, 3000);
  });
}

// call addName
addName({ firstName: 'Joe', lastName: 'Smith' })
  .then(getNames)
  .catch((error) => console.log(error));

В этом случае addName возвращает обещание, которое, в зависимости от того, произошла ли ошибка, разрешается или отклоняется. После разрешения промиса вызывается метод getNames с использованием метода .then , а любые ошибки обрабатываются с использованием метода .catch .

Промисы используются для получения данных и т. д. При работе с промисами вы обычно имеете дело с ответом, а не с его созданием.

Важно понимать, что после обработки разрешенного значения промиса с помощью метода then вы не можете снова вызвать его для того же промиса. Вместо этого вы можете предпочесть обрабатывать несколько обещаний одновременно, используя Promise.all, а затем ждать, пока каждое из них разрешится, прежде чем предпринимать дальнейшие действия.

Обещание.все

Для обработки нескольких обещаний вы можете использовать методPromise.all. Он принимает массив обещаний в качестве аргументов и возвращает одно обещание, которое разрешается после разрешения каждого обещания во входных данных. Он отклоняется, если какое-либо обещание на входе отклонено.

function addName(name) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // to resolve
      const error = false; // first check errors
      if (!error) {
        resolve();
      } else {
        reject('Error: Something went wrong!');
      }
    }, 3000);
  });
}

// Promises
const promise1 = Promise.resolve('Hello World!');
const promise2 = 20;
const promise3 = new Promise((resolve, reject) => setTimeout(resolve, 2000, 'Goodbye!'));
const promise4 = fetch('url').then(res => res.json());

// Promise.all
Promise.all([promise1, promise2, promise3, promise4])
  .then(values => console.log(values))
  .catch(error => console.log(error));

При работе с несколькими промисами async/await — это способ написания асинхронного кода, который упрощает чтение и запись.

асинхронно / жду

Прежде всего, что такое ключевые слова async/await и зачем нам их использовать?

Асинхронные функции — это функции, которые выполняются параллельно. Когда одновременно происходит много вещей, асинхронный код может быть сложным для понимания. Одним из примеров асинхронной функции является setTimeout().

Два ключевых слова async andawait используются для того, чтобы сделать код более похожим на синхронный код. Сохраняя преимущества асинхронного кода, он позволяет легко следовать коду.

Давайте развернем каждый по одному.

Что такое асинхронность?

Ключевое словоasync используется перед функцией, чтобы показать, что функция является асинхронной. Thisasync заставляет функцию возвращать обещание. Обещания — это объекты, которым требуется некоторое время для создания кода и ожидания результата кода.

Синтаксис:

async function funName(parameter1, parameter2, …paramaterN) {

// code statements here..

}

Пояснение:

  • asyncэто ключевое слово, которое используется, чтобы показать, что функция является асинхронной.
  • function это ключевое слово
  • funName это имя функции
  • parameters — это значения, которые передаются функции

Что ждет?

В JavaScript ключевое слово await keyword сочетается с ключевым словом async, чтобы отсрочить выполнение кода во время ожидания разрешения промиса.

Синтаксис:

result = await promise;

Пример:

async function init(){
   await addName ({ firstName: 'Joe', lastName:'Smith' });
   getNames();
}
init( );

Пример:

Давайте создадим функцию, которая получает информацию с сервера, обрабатывает ее и возвращает обещание.

async/await это более приятный способ работы с промисами, чем писать .then то, что мы должны писать в промисах.

const personNames = [
  { firstName: 'David', lastName:'Smith' },
  { firstName: 'Andrew', lastName:'Tate' }
];
function getNames( ){ 
  setTimeout(( ) => {
  let result = ' ';
  personNames.forEach((name, index) =>{
  result += `<li>${name.firstName}</li>`
});
document.body.innerHTML = result;
}, 2000);
} 

// add new person name
function addName( name ) {
  return Promise((resolve, reject) =>{
  setTimeout(() => {
  personNames.push(name);

// to resolve 
const error = false; // first check errors
  if(!error){
  resolve();
} else{
  reject( 'Error: Something went wrong!');
}
}, 3000);
});
}

// async/await
async function init(){
  await addName ({ firstName: 'Joe', lastName:'Smith' });
  getNames();
}
init( );

В этой программе определен асинхронный метод init(), который использует функции addName() и setTimeout для выполнения getNames() с 3-секундной задержкой после добавления нового имени в массив personNames().

Функция setTimeout() используется для задержки выполнения функции getNames() на 2 секунды при переборе массива personNames для создания HTML-списка имен.

Примерно через 5 секунд после выполнения кода в теле документа должен появиться неупорядоченный список с именами всех трех человек в personNames: «Дэвид», «Эндрю» и «Джо».

асинхронно/ожидание получения данных

Этот код, упомянутый ниже, поможет вам получить данные из API и отобразить эти данные элегантным способом.

// async/await with fetch
async function fetchData() {
const res = await fetch('url'); // this returns a promise

const data = await res.json( );

console.log(data);
}
fetchData();

В этом коде асинхронный метод fetchData() отправляет HTTP-запрос с использованием fetch(), а функция fetch() возвращает объект Response.

Заворачивать

Это обертка. Я надеюсь, что этот пост помог вам лучше понять термины async и await. Спасибо за чтение. Если вам понравилось читать, поделитесь с друзьями.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Присоединяйтесь к нашему сообществу Discord и следите за нами в Twitter, LinkedIn и YouTube.

Узнайте, как привлечь внимание к своему стартапу с помощью Circuit.