Используйте 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 }))
            )
        })
    )
}
Другие вопросы по тегам