Async и Await не работают в Axios React

у меня проблема:

Я хочу, чтобы мой axios выполнил требование и после этого сделал this.setState с результатом, сохраненным в переменной.

Мой код:

componentDidMount() {
  let mails = [];
  axios.get('/api/employee/fulano')
    .then(res => this.setState({
      employees: res.data
    }, () => {

      this.state.employees.map(i => {
        async axios.get(`/api/status/${i.mail}`)
          .then(res => {
            mails.push(res.data)
            await this.setState({
              mails: mails
            })
          })
          .catch(err => console.info(err))
      })
    }))
    .catch(err => console.info(err))
}

Но дает синтаксис ошибки.

Лучшее объяснение: я хочу сохранить все результаты карты в переменной mails, а затем использовать setState для изменения результата только на время.

Кто-нибудь может сказать мне, где я блуждаю? Пожалуйста.

Почему вы даже пытаетесь использовать async / await, если вас устраивает использование then и catch?

Bergi 12.10.2018 19:50

Чтобы решить вашу актуальную проблему, вам нужен Promise.all.

Bergi 12.10.2018 19:51
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
2
6 481
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Это должно работать:

    componentDidMount() {
        axios.get('/api/employee/fulano')
         .then(res => this.setState({
          employees: res.data
         }, () => {

           this.state.employees.map(i => {
           axios.get(`/api/status/${i.mail}`)
             .then( async (res) => { // Fix occurred here
                let mails = [].concat(res.data)
                await this.setState({
                  mails: mails
             })
          })
          .catch(err => console.info(err))
        })
      }))
         .catch(err => console.info(err))
     }

добро пожаловать в stackoverflow! Пожалуйста, уточните еще немного. Другой ответ выглядит лучше, даже если он был дан после вашего: и это потому, что есть объяснение.

Nathan Ripert 12.10.2018 19:29

Вы поставили async не в то место

async следует помещать в определение функции, а не в вызов функции

componentDidMount() {
    let mails = [];
    axios.get('/api/employee/fulano')
    .then(res => this.setState({
        employees: res.data
    }, () => {
        this.state.employees.map(i => {
            axios.get(`/api/status/${i.mail}`)
            .then(async (res) => {
                mails.push(res.data)
                await this.setState({
                    mails: mails
                })
            })
            .catch(err => console.info(err))
        })
    }))
    .catch(err => console.info(err))
}
Ответ принят как подходящий

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

Ключевое слово await необходимо использовать для выражения, которое возвращает Promise, и хотя setState - это async, оно не возвращает обещание, и, следовательно, await не будет работать с ним.

Ваше решение будет выглядеть так

componentDidMount() {
  let mails = [];
  axios.get('/api/employee/fulano')
    .then(res => this.setState({
      employees: res.data
    }, async () => {

      const mails = await Promise.all(this.state.employees.map(async (i) => { // map function contains async code
        try {
             const res = await axios.get(`/api/status/${i.mail}`)
             return res.data;
        } catch(err) { 
            console.info(err)
        }
      })
      this.setState({ mails })
    }))
    .catch(err => console.info(err))
}

Здравствуйте, спасибо за ответ, рада этому .. Но дано: await is a reserved word (20:22), почему?

Jota 12.10.2018 19:44

@Jota, извините, отсутствовало ключевое слово async в функции обратного вызова setState, обновил мой ответ

Shubham Khatri 12.10.2018 19:46

Смешивать async/await с .then/.catch - не лучшая практика. Вместо этого используйте одно или другое. Вот пример того, как вы могли бы это сделать, используя ТОЛЬКОasync/await и ТОЛЬКО one this.setState() (ссылка на функцию Promise.each):

componentDidMount = async () => {
  try {    
    const { data: employees } = await axios.get('/api/employee/fulano'); // get employees data from API and set res.data to "employees" (es6 destructing + alias)

    const mails = []; // initialize variable mails as an empty array

    await Promise.each(employees, async ({ mail }) => { // Promise.each is an asynchronous Promise loop function offered by a third party package called "bluebird"
      try {
       const { data } = await axios.get(`/api/status/${mail}`) // fetch mail status data
       mails.push(data); // push found data into mails array, then loop back until all mail has been iterated over
      } catch (err) { console.error(err); }
    })

    // optional: add a check to see if mails are present and not empty, otherwise throw an error.

    this.setState({ employees, mails }); // set employees and mails to state
  } catch (err) { console.error(err); }

}

Другие вопросы по теме