171 lines
6.9 KiB
Markdown
171 lines
6.9 KiB
Markdown
---
|
||
id: 5a24c314108439a4d4036156
|
||
title: Використання Middleware для опрацювання асинхронних дій
|
||
challengeType: 6
|
||
forumTopicId: 301451
|
||
dashedName: use-middleware-to-handle-asynchronous-actions
|
||
---
|
||
|
||
# --description--
|
||
|
||
До цього моменту в завданнях ми уникали обговорення асинхронних дій, хоча вони є обов'язковою частиною веб-розробки. У певний момент вам прийдеться викликати асинхронні кінцеві точки у вашому додатку Redux. Отже, як опрацьовувати ці всі типи запитів? Задля цього Redux було спеціально розроблено проміжне програмне забезпечення Redux Thunk. Нижче наведено як використовувати цей додаток з Redux.
|
||
|
||
Для використання проміжного програмного забезпечення Redux Thunk, передайте його як аргумент до `Redux.applyMiddleware()`. Ця команда передається далі, як другий вибірковий параметр для функції `createStore()`. Щоб побачити це, подивіться на код, розміщений внизу редактора. Таким чином для створення асинхронної дії ви повертаєте функцію в генераторі дії, яка отримує `dispatch`, як аргумент. У межах цієї функції ви можете відправляти дії та виконувати асинхронні запити.
|
||
|
||
У цьому прикладі асинхронний запит моделюється за допомогою команди `setTimeout()`. Загальноприйнято надсилати дію перед початком будь-якої асинхронної поведінки, щоб стан вашої програми знав про те, що запитуються деякі дані (наприклад, у цьому стані може показуватися значок завантаження). Як тільки ви отримуєте дані, ви відправляєте іншу дію, яка переносить дані, як інформаційне наповнення разом з інформацією про завершену дію.
|
||
|
||
Пам'ятайте, що ви передаєте `dispatch`, як параметр для цього спеціального генератора дії. Це те, що ви будете використовувати для відправлення ваших дій. Ви просто передасте дію безпосередньо для відправлення, а проміжне програмне забезпечення потурбується про все інше.
|
||
|
||
# --instructions--
|
||
|
||
Пропишіть обидві команди відправлення у створювачі дії `handleAsync()`. Відправте `requestingData()` перед `setTimeout()`(модельований АРІ запит). Після того, як ви отримаєте (pretend) дані, відправте дію `receivedData()`, у якій передасте ці дані. Тепер ви знаєте, як опрацьовувати асинхронні дії у Redux. Все інше продовжує поводитися як і раніше.
|
||
|
||
# --hints--
|
||
|
||
Генератор дії `requestingData` має повернути об'єкт типу, що дорівнює значенню `REQUESTING_DATA`.
|
||
|
||
```js
|
||
assert(requestingData().type === REQUESTING_DATA);
|
||
```
|
||
|
||
Генератор дії `receivedData` має повернути об'єкт типу, що дорівнює значенню `RECEIVED_DATA`.
|
||
|
||
```js
|
||
assert(receivedData('data').type === RECEIVED_DATA);
|
||
```
|
||
|
||
`asyncDataReducer` має бути функцією.
|
||
|
||
```js
|
||
assert(typeof asyncDataReducer === 'function');
|
||
```
|
||
|
||
Відправлення генератора дії `requestingData` має оновити зберігання властивості `state` для отримання `true`.
|
||
|
||
```js
|
||
assert(
|
||
(function () {
|
||
const initialState = store.getState();
|
||
store.dispatch(requestingData());
|
||
const reqState = store.getState();
|
||
return initialState.fetching === false && reqState.fetching === true;
|
||
})()
|
||
);
|
||
```
|
||
|
||
Посилання `handleAsync` має спочатку відправити дію про запит даних, а потім, після затримки, відправити отримані дані.
|
||
|
||
```js
|
||
assert(
|
||
(function () {
|
||
const noWhiteSpace = __helpers.removeWhiteSpace(handleAsync.toString());
|
||
return (
|
||
noWhiteSpace.includes('dispatch(requestingData())') === true &&
|
||
noWhiteSpace.includes('dispatch(receivedData(data))') === true
|
||
);
|
||
})()
|
||
);
|
||
```
|
||
|
||
# --seed--
|
||
|
||
## --seed-contents--
|
||
|
||
```js
|
||
const REQUESTING_DATA = 'REQUESTING_DATA'
|
||
const RECEIVED_DATA = 'RECEIVED_DATA'
|
||
|
||
const requestingData = () => { return {type: REQUESTING_DATA} }
|
||
const receivedData = (data) => { return {type: RECEIVED_DATA, users: data.users} }
|
||
|
||
const handleAsync = () => {
|
||
return function(dispatch) {
|
||
// Dispatch request action here
|
||
|
||
setTimeout(function() {
|
||
let data = {
|
||
users: ['Jeff', 'William', 'Alice']
|
||
}
|
||
// Dispatch received data action here
|
||
|
||
}, 2500);
|
||
}
|
||
};
|
||
|
||
const defaultState = {
|
||
fetching: false,
|
||
users: []
|
||
};
|
||
|
||
const asyncDataReducer = (state = defaultState, action) => {
|
||
switch(action.type) {
|
||
case REQUESTING_DATA:
|
||
return {
|
||
fetching: true,
|
||
users: []
|
||
}
|
||
case RECEIVED_DATA:
|
||
return {
|
||
fetching: false,
|
||
users: action.users
|
||
}
|
||
default:
|
||
return state;
|
||
}
|
||
};
|
||
|
||
const store = Redux.createStore(
|
||
asyncDataReducer,
|
||
Redux.applyMiddleware(ReduxThunk.default)
|
||
);
|
||
```
|
||
|
||
# --solutions--
|
||
|
||
```js
|
||
const REQUESTING_DATA = 'REQUESTING_DATA'
|
||
const RECEIVED_DATA = 'RECEIVED_DATA'
|
||
|
||
const requestingData = () => { return {type: REQUESTING_DATA} }
|
||
const receivedData = (data) => { return {type: RECEIVED_DATA, users: data.users} }
|
||
|
||
const handleAsync = () => {
|
||
return function(dispatch) {
|
||
dispatch(requestingData());
|
||
setTimeout(function() {
|
||
let data = {
|
||
users: ['Jeff', 'William', 'Alice']
|
||
}
|
||
dispatch(receivedData(data));
|
||
}, 2500);
|
||
}
|
||
};
|
||
|
||
const defaultState = {
|
||
fetching: false,
|
||
users: []
|
||
};
|
||
|
||
const asyncDataReducer = (state = defaultState, action) => {
|
||
switch(action.type) {
|
||
case REQUESTING_DATA:
|
||
return {
|
||
fetching: true,
|
||
users: []
|
||
}
|
||
case RECEIVED_DATA:
|
||
return {
|
||
fetching: false,
|
||
users: action.users
|
||
}
|
||
default:
|
||
return state;
|
||
}
|
||
};
|
||
|
||
const store = Redux.createStore(
|
||
asyncDataReducer,
|
||
Redux.applyMiddleware(ReduxThunk.default)
|
||
);
|
||
```
|