Использовать выборку вместо ajax с помощью редукционного наблюдаемого

В 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(), а также любой другой API AJAX; хотя некоторые адаптируются легче, чем другие!

API fetch() возвращает Promise, для которого RxJS v5 имеет встроенную поддержку. Большинство операторов, ожидающих наблюдаемого, могут потреблять Promises как есть (например, mergeMap, switchMap и т.д.). Но часто вам нужно применить Rx-операторы к Promise, прежде чем передавать их вместе с остальной частью вашего Epic, поэтому вы часто захотите обернуть Promise внутри наблюдаемого.

Вы можете перенести обещание в наблюдаемое с помощью 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 не может быть отменен. (с момента написания)

Ответ 2

Небольшая корректировка @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 }))
            )
        })
    )
}