Как я могу сохранить данные из функции выборки, используя async / await

#javascript #asynchronous #async-await #get #fetch

#javascript #асинхронный #асинхронный-ожидание #получить #принести

Вопрос:

Кодекс:

 const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");

const raw = JSON.stringify({
  email: "example@gmail.com",
  password: "password",
});

const requestOptions = {
  method: "POST",
  headers: myHeaders,
  body: raw,
  redirect: "follow",
};

let data;

fetch("/users/login", requestOptions)
  .then((response) => response.text())
  .then((result) => {
    data = JSON.parse(result);
  })
  .catch((error) => console.log("error", error));

console.log(data);
 

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

Ответ №1:

Ваш вызов console.log выполняется до завершения запроса и получения данных.

Порядок выполнения отличается от порядка написания вашего кода. Вероятная цепочка событий такова:

  • Создайте неопределенную переменную с именем data
  • Запустите запрос /users/login с помощью fetch API, который будет выполняться асинхронно
  • Вызов console.log с ссылкой на data который все еще undefined
  • Запрос завершен, поэтому обратный вызов, переданный fetch.then , вызывается и data определяется

Вам нужно будет дождаться завершения запроса и анализа ответа, прежде чем что — то делать data .

Вы можете сделать это несколькими различными способами. Использование обещаний:

 let data;

fetch("/users/login", requestOptions)
  .then((response) => response.text())
  .then((result) => {
    data = JSON.parse(result);
    // Now that `data` has been defined, we can do something with it
    console.log(data);
  })
  .catch((error) => console.log("error", error));
 

С помощью async / await

 // Note the async keyword
async function foobar() {
  let data;

  // Note the await keyword
  await fetch("/users/login", requestOptions)
    .then((response) => response.text())
    .then((result) => {
      data = JSON.parse(result);
    })
    .catch((error) => console.log("error", error));
    
  console.log(data);
}

// There are other improvements that could be made to this example also
// to make it more idiomatic. For example:

async function foobar() {
  let data;

  // Use try/catch instead of `Promise.catch`
  try {
    const response = await fetch('/users/login', requestOptions);
    // Use the `.json` method on the fetch response object
    data = await response.json();
  } catch (error) {
    console.log('error', error);
  }

  console.log(data);
}
 

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

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

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

Одна вещь, которую следует иметь в виду при использовании async / await, заключается в том, что await ключевое слово может использоваться только в функции, которая помечена как асинхронная с async ключевым словом, как в приведенном выше примере.

Ответ №2:

Вы не можете распечатать переменную, значение которой инициализировано в асинхронном блоке.

Данные будут напечатаны правильно, если вы изменили их таким образом.

 fetch("/users/login", requestOptions)
  .then((response) => response.text())
  .then((result) => {
    const data = JSON.parse(result);
    console.log(data);
  })
  .catch((error) => console.log("error", error));
 

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

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

 const myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");

const raw = JSON.stringify({
  email: "example@gmail.com",
  password: "password",
});

const requestOptions = {
  method: "POST",
  headers: myHeaders,
  body: raw,
  redirect: "follow",
};

try{
  const data = await fetch("/users/login", requestOptions);
  console.log(data);
catch(err){
  console.log('error', err);
}