Используйте fetch вместо ajax с redux-observable
В redux-observable
Можно ли использовать isomporphic-fetch вместо Rx.DOM.ajax?
1 ответ
(Заметка: RX.DOM.ajax
из RxJS v4, и не работает с redux-observable
который требует RxJS v5. Эквивалент в v5 Rx.Observable.ajax
или же import { ajax } from 'rxjs/observable/ajax';
)
Это действительно возможно использовать fetch()
а также любой другой AJAX API; хотя некоторые адаптируются легче, чем другие!
fetch()
API возвращает Promise
, для которого RxJS v5 имеет встроенную поддержку. Большинство операторов, которые ожидают, что наблюдаемое может использовать обещания как есть (например, mergeMap
, switchMap
, так далее). Но часто вам захочется применить операторы Rx к Обещанию, прежде чем передать его остальной части Epic, поэтому вам часто захочется обернуть Обещание в Observable.
Вы можете обернуть Обещание в Observable с помощью Observable.from(promise)
Вот пример, где я выбираю пользователя, запрашиваю ответ JSON, а затем оборачиваю обещание в наблюдаемую:
const api = {
fetchUser: id => {
const request = fetch(`https://jsonplaceholder.typicode.com/users/${id}`)
.then(response => response.json());
return Observable.from(request);
}
};
Затем вы можете использовать это в своем Epic и применять любые операторы, которые вы хотите:
const fetchUserEpic = action$ =>
action$.ofType(FETCH_USER)
.mergeMap(action =>
api.fetchUser(action.payload) // This returns our Observable wrapping the Promise
.map(payload => ({ type: FETCH_USER_FULFILLED, payload }))
);
Вот JSBin с этим рабочим примером: https://jsbin.com/fuwaguk/edit?js,output
Если у вас есть контроль над кодом API, в идеале вы должны использовать Observable.ajax
(или любые другие утилиты AJAX, основанные на Observable), потому что Promises не могут быть отменены. (на момент написания статьи)
Сделал небольшую корректировку в @jayphelps, чтобы этот код работал на меня. Надеюсь, это поможет сэкономить чье-то время.
import { FETCH_USER } from './actions'
import { ofType } from 'redux-observable'
import { map, mergeMap } from 'rxjs/operators'
import { from } from 'rxjs'
const fetchUserEpic = action$ => {
return action$.pipe(
ofType(FETCH_USER),
mergeMap((action = { user: 'redux-observable' }) => {
const getRequest = (user) => {
const request = fetch(`https://api.github.com/users/${user}`)
.then(response => response.json())
return from(request)
}
return getRequest(action.user).pipe(
map(payload => ({ type: FETCH_USER_FULFILLED, payload }))
)
})
)
}