# Axios и Redux-Thunk, асинхронные запросы к бэкенду
## fetch
Привычный способ обращения к серверу - функция fetch:
```js
const response = await fetch(url, options);
const json = await response.json();
```
## Axios возвращает Promise
Как и fetch, axios возвращает Promise. Синтаксис немного отличается:
```js
const response = await fetch(url, options);
const json = await response.json();
```
## В чём разница?
- корректная поддержка cookie-заголовков
- более гибкие настройки
- более выразительный интерфейс
## Установка
npm:
```sh
npm install axios
```
yarn:
```sh
yarn add axios
```
## Общие запросы
```js
// Send a POST request
axios({
method: 'post',
url: '/user/12345',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
}
});
// Send a GET request (default method)
axios('/user/12345');
```
## Запросы по методам
- axios.request(config)
- axios.get(url[, config])
- axios.delete(url[, config])
- axios.head(url[, config])
- axios.options(url[, config])
- axios.post(url[, data[, config]])
- axios.put(url[, data[, config]])
- axios.patch(url[, data[, config]])
## Настройки
```js
{
url: '/user',
method: 'get', // default
// базовый адрес, к нему добавляется свойство url для формирования полного адреса
baseURL: 'https://some-domain.com/api/',
// преобразование всех запросов перед отправкой
transformRequest: [function (data, headers) {
return data;
}],
// преобразование ответа
transformResponse: [function (data) {
// Do whatever you want to transform the data
return data;
}],
// дополнительные заголовки
headers: {'X-Requested-With': 'XMLHttpRequest'},
// параметры в адресной строке, GET-параметры
params: {
ID: 12345
},
// данные для не GET-запросов (POST, PUT и тд), сюда передаётся тело запроса
data: {
firstName: 'Fred'
},
// передача данных в виде строки
data: 'Country=Brasil&City=Belo Horizonte',
// таймаут соединения
timeout: 1000, // default is `0` (no timeout)
// передача cookie-файлов
withCredentials: false, // default
// 401-авторизация
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
// обработка полученных данных перед отдачей результата
// options are: 'arraybuffer', 'document', 'json', 'text', 'stream', 'blob'
responseType: 'json', // default
// ограничение размера передаваемого содержимого
maxContentLength: 2000,
maxBodyLength: 2000,
// максимальное число переходов по переадресациям от сервера
maxRedirects: 21, // default
// инструменты для отмены запроса
// an alternative way to cancel Axios requests using AbortController
signal: new AbortController().signal,
}
```
## Ответ
axios возвращает ответ в виде объекта со следующими свойствами
```js
axios.get('/user/12345')
.then(function (response) {
console.log(response.data);
console.log(response.status);
console.log(response.statusText);
console.log(response.headers);
console.log(response.config);
});
```
## Отмена запроса
```js
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// cancel the request
controller.abort()
```
## Настройки в рамках клиента
Для разделения настроек при работе с несколькими API, можно создать свой экземпляр axios через axios.create
```js
const instance = axios.create();
instance.defaults.timeout = 2500;
instance.get('/longRequest', {
timeout: 5000
});
```
## Шаблон Посредник
Представляет цепочку функций:
- каждая обрабатывает свою часть запроса
- если в процессе проверки возникают ошибки, следующие в цепочке функции не запустятся
```js
const user = {
name: 'Oleg',
age: 18,
active: true
};
const checkAge = (data, next) => {
if (data.age >= 18) {
return next();
}
console.log('Вы слишком молоды!');
}
const checkLastName = (data, next) => {
if (data.lastName) {
return next();
}
console.log('У вас нет фамилии!');
}
const checkActive = (data, next) => {
if (data.active) {
return next();
}
console.log('Будьте активнее!');
};
const action = (data) => {
console.log('вы справились!');
}
const middlewares = [checkAge, checkLastName, checkActive, action];
const run = (payload, chain) => {
const done = () => true;
for (const fn of chain) {
if (fn(payload, done) !== true) {
return;
}
}
}
run(user, middlewares);
```
## Redux Thunk
По факту входит в состав redux toolkit и позволяет запускать дочерние и отложенные действия
```js
export const incrementIfOdd = (amount) => (dispatch, getState) => {
const currentValue = selectCount(getState());
if (currentValue % 2 === 1) {
dispatch(incrementByAmount(amount));
}
};
```
## Преимущества
- Запуск действий из действий (цепочка действий)
- Даёт доступ к dispatch
- Поддержка Promise в действиях