Що робить abort() у thunk?
Коротка відповідь
У Redux Toolkit
abort()використовується для скасування виконання асинхронного thunk'а.Він зупиняє асинхронний процес (наприклад, fetch) і викликає
rejectedстан з причиною"Aborted".
Де використовується abort()
Метод abort() доступний всередині функції, яку ти передаєш в createAsyncThunk:
const fetchUser = createAsyncThunk(
'user/fetch',
async (id, { signal, rejectWithValue }) => {
const controller = new AbortController()
signal.addEventListener('abort', () => controller.abort())
try {
const res = await fetch(`/api/users/${id}`, { signal: controller.signal })
return await res.json()
} catch (err) {
if (err.name === 'AbortError') {
return rejectWithValue('Запит було скасовано')
}
throw err
}
}
)Тепер - якщо цей thunk буде скасований, RTK викличе controller.abort() і fetch перерветься.
Як abort() працює всередині Redux Toolkit
Коли ти створюєш thunk через createAsyncThunk, RTK додає до нього:
- спеціальний об'єкт
abortController; - сигнал
signal, який можна слухати; - і метод
abort(), який ти можеш викликати вручну.
const promise = dispatch(fetchUser(5))promise - це не просто Promise!
Він має методи:
promise.abort()
promise.unwrap()Приклад: як скасувати асинхронний thunk
const promise = dispatch(fetchUser(5))
// десь пізніше...
promise.abort()Що станеться:
- Redux Toolkit викличе
AbortController.abort() - Усі fetch-запити, "прив'язані" до
signal, перерваються - Thunk не перейде в fulfilled
- Замість цього викличеться rejected з помилкою
"Aborted"
Що відбувається під капотом
Ось спрощено, як RTK робить це всередині:
function createAsyncThunk(typePrefix, payloadCreator) {
return (arg) => (dispatch, getState, extra) => {
const abortController = new AbortController()
const thunkPromise = new Promise(async (resolve, reject) => {
try {
const result = await payloadCreator(arg, {
signal: abortController.signal,
dispatch,
getState,
})
dispatch({ type: `${typePrefix}/fulfilled`, payload: result })
resolve(result)
} catch (err) {
if (abortController.signal.aborted) {
dispatch({ type: `${typePrefix}/rejected`, error: 'Aborted' })
}
reject(err)
}
})
thunkPromise.abort = () => abortController.abort()
return thunkPromise
}
}Приклад: використання в React
const dispatch = useDispatch()
useEffect(() => {
const promise = dispatch(fetchUser(5))
return () => {
// Якщо компонент розмонтується → скасовуємо запит
promise.abort()
}
}, [dispatch])Тепер, якщо компонент розмонтується до завершення запиту,
fetchUser автоматично перерветься і не намагатиметься оновити стан.
Чому це важливо
| Проблема | Як вирішує abort() |
|---|---|
| Компонент розмонтувався під час запиту | Зупиняє виконання, щоб не оновлювати неіснуючий компонент |
| Користувач швидко перемкнув вкладку / сторінку | Можна скасувати старі запити |
| Потрібно скасувати довгу операцію | abort() миттєво перериває thunk |
| Уникає гонок даних ("race conditions") | Продовжує виконуватися тільки останній активний thunk |
Що повертає скасований thunk
Коли ти викликаєш abort(), createAsyncThunk:
- диспетчить екшен
{ type: '.../rejected', error: { message: 'Aborted' } } - не виконує код далі
- повертає Promise, який відхиляється з помилкою
"Aborted"
Можна відловити:
const promise = dispatch(fetchUser(5))
promise
.unwrap()
.then(data => console.log('OK', data))
.catch(err => {
if (err.name === 'AbortError') console.log('Запит скасовано')
})Підсумок
| Що | Опис |
|---|---|
abort() | Скасовує виконання асинхронного thunk |
| Де викликається | У Promise, який повертає dispatch(thunk()) |
| Що робить | Перериває fetch / async-функцію через AbortController |
| Результат | Redux викликає .../rejected з помилкою "Aborted" |
| Коли корисно | При скасуванні запитів, зміні сторінки, розмонтуванні компонента |
Підсумкове формулювання:
Метод
abort()у thunk використовується для переривання асинхронної операції, щоб уникнути непотрібних оновлень стану і гонок даних. Він працює через вбудованийAbortController, переданий уsignal, і викликає rejected-стан thunk з помилкою"Aborted".
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.