Недавно решил оптимизировать запросы, убрать полностью с сайта jQuery и перейти на axios. Все бы ничего, удаление и добавление записи пошло норм. А вот с валидацией наступила полная засада. Просто не возвращался reject а красным куча ошибок в консоли. Порыл интернет и вот что нашел: При обработке запросов ajax с помощью Laravel часто возникают две ошибки: 419 и 422.

Как получить ответ валидации Laravel и ошибки валидации с помощью axios

Недавно решил оптимизировать запросы, убрать полностью с сайта jQuery и перейти на axios.

Все бы ничего, удаление и добавление записис рпошло норм. А вот с валидацией наступила полная засада. Просто не возвращался reject а красным куча ошибок в консоли. Порыл интернет и вот что нашел:

При обработке запросов ajax с помощью Laravel часто возникают две ошибки: 419 и 422.

Код 419 говорит о том, что у вас отсутствует csrf token.

Чтобы решить эту проблему, просто поместите это в свой head:

<meta name="csrf-token" content="{{ csrf_token() }}" /> 

И передайте его с каждым запросом, который вы отправляете в Laravel. (Для маршрутов в  web.php файле) Если вы используете axios, вы можете либо добавить его в свою глобальную конфигурацию axios: 

axios.defaults.headers = {
  'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
},

Или укажите при создании экземпляра axios: 

const instance = axios.create({
  headers: {
    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content'),
  },
});

Ошибка axios 422 Unprocessable Entity решение

Эта ошибка возникает при сбое проверки со стороны сервера. Если вы попросите Laravel обновить вашу страницу после POST запроса, вы получите ошибки в @errors директиве и прочем, но обычно эти запросы и ответы идут через ajax либо потому, что так удобнее пользователям, либо вы используете фреймворк, ​​​​как React или Vue. 

Вот как вы можете решить 422 Unprocessable Entity проблему axios.

Предположим, вы проверяете свою форму с помощью полей ввода электронной почты и пароля:

$request->validate([
  'email' => 'required|min:4',
  'password' => 'required|min:9'
]);

Поскольку  axios — это библиотека на основе Promise, вы можете отлавливать ошибки в  catch блоках. Однако проблема в том, что даже если вы добавите блок catch после вашего  then, это не поможет вам получить информацию об ошибке в вашем браузере. При попытке его логировать вы скорее всего получите что-то вроде этого вместо аккуратного json с ошибками: 

log.png

К счастью, решение простое. Когда вы получаете доступ к данным об ошибках, используйте  error.response вместо этого  error в своем блоке catch следующим образом: 

axios
  .post(endpoint, body, headers)
  .then(response => {
    // Do fancy stuff
  })
  .catch(error => {
    console.log(error.reponse); // logs an object to the console

    // Do something with error data
  });

Здесь error.response объект с несколькими полезными свойствами, такими как statusstatusText и data

Последнее то, что мы ищем. Там можно найти message свойство с общим описанием и errors объект с подробными ошибками проверки. 

В error.response.data.errors объекте ключами являются входные имена, а значениями являются массивы(!) строк, описывающих ошибки.

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

Если вы не знакомы с концепцией перехватчиков, вы можете думать об этом следующим образом:

  • Для запросов они изменяют данные вашего запроса перед отправкой на сервер,
  • Для ответов они изменяют ответ перед всеми вашими блоками then и .catch

Если вы хотите узнать больше, ознакомьтесь с документацией axios по этой теме.

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

instance.interceptors.response.use(
  response => response,
  error => Promise.reject(error.response)
);

Обратите внимание, что мы пересылаем как обычный ответ, так и сообщение об ошибке.

Вот мой финальный код

async function postData(_url, query) {
    let _token = <strong><em>document</em></strong>.querySelector('meta[name="csrf-token"]').content;

    return await axios.post(_url, query, {
        headers: {
            'Content-Type': 'application/json',
            'X-CSRF-TOKEN': _token,
            'X-Requested-With': 'XMLHttpRequest',
        }
    }).then(response => {
        // console.log(response.data)
        return response.data;
    }).catch(error => {
        // console.log(error.response);
        return error.response;
    });

}

А вызываю его вот так:

 const args = JSON.stringify({
              title: title,
              description: description,
              location: location,
              phone: phone,
              email: email,
              website: website            
          });

const query = await postData(_url, args);

И в основном это все!

Если вам есть что добавить, нашли ошибку или просто хотите поболтать, свяжитесь со мной в комментах или напишите по электронной почте 🙂