2017-05-02 2 views
2

Wenn ich im folgenden Code getCurrentPositionEpic auskommentieren, funktioniert die App. Aber wenn ich überlasse es unkommentiert ich den Fehler:redux-observable Actions müssen einfache Objekte sein. Verwenden Sie benutzerdefinierte Middleware für asynchrone Aktionen

Actions must be plain objects. Use custom middleware for async actions.

export const rootEpic = combineEpics(
    fetchCategoriesEpic, 
    getCurrentLocationEpic, 
    getCurrentPositionEpic 
) 

const store = createStore(
    rootReducer, 
    initialState, 
    composeWithDevTools(
    applyMiddleware(createEpicMiddleware(rootEpic)) 
) 
) 

location.epic.js

const getCurrentPosition$ = getCurrentPositionObservable(
    { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 } 
) 

getCurrentPosition$.subscribe(
    (position) => { 
    console.log(position) 
    const positionObject = { 
     lat: position.coords.latitude, 
     lng: position.coords.longitude 
    } 
    //store.dispatch(updateRegion(positionObject)) 
    //getCurrentLocation(positionObject) 
    }, 
    (err) => { 
    console.log('Error: %s', err) 
    }, 
() => { 
    console.log('Completed') 
    }) 

export const getCurrentLocationEpic = action$ => 
    action$.ofType(GET_CURRENT_LOCATION) 
    .mergeMap(() => 
     Observable.fromPromise(Geocoder.geocodePosition(makeSelectLocation())) 
     .flatMap((response) => Observable.of(
      getCurrentLocationFulfilled(response) 
     )) 
     .catch(error => Observable.of(getCurrentLocationRejected(error))) 
    ) 

export const getCurrentPositionEpic = action$ => 
    action$.ofType(GET_CURRENT_POSITION) 
    .mapTo(() => getCurrentPosition$ 
     .flatMap((response) => Observable.of(
     getCurrentPositionFulfilled(response) 
    )) 
     .catch(error => Observable.of(getCurrentLocationRejected(error))) 
    ) 

der folgende Code ist nur ein Helfer verwendet, um reagieren zu konvertieren nativen navigator.geolocation.getCurrentPosition auf einem beobachtbar anstelle einer Funktion, die einen Rückruf nimmt.

callBackToObservable.js

import { Observable } from 'rxjs' 

export const getCurrentPositionObservable = Observable.bindCallback(
    (options, cb) => { 
    if (typeof options === 'function') { 
     cb = options 
     options = null 
    } 
    navigator.geolocation.getCurrentPosition(cb, null, options) 
    }) 

Was den Fehler verursacht werden könnte?

versuchen, im Laden vorbei:

export const getCurrentPositionFulfilledEpic = (action$, store) => 
    action$.ofType(GET_CURRENT_POSITION_FULFILLED) 
     .mergeMap(() =>{ 
    console.log(store)***************** store is populated here 
    return Observable.fromPromise(Geocoder.geocodePosition({ 
    lat: store.getState().get('searchForm').get('position').lat,***but not here 
    lng: store.getState().get('searchForm').get('position').lng 
    })) 
    .flatMap((response) => Observable.of(
     getCurrentLocationFulfilled(response) 
    )) 
    .catch(error => Observable.of(getCurrentLocationRejected(error))) 
} 
) 

Mit https://github.com/devfd/react-native-geocoder für Geocoder.geocodePosition

Antwort

3

Das Problem ist, um Ihre Nutzung der mapTo. Du sagst im Grunde: "Zeige diese Aktion einem Observablen an", also gibt dein Epos jetzt ein Observable of Observable von Actions Observable<Observable<Action>> statt nur eines Observable of actions zurück.

Anders gesagt, Ihr Epos gibt jetzt Observables aus, anstatt Aktionen zu senden. Sie müssen stattdessen einen Merging-Strategieoperator wie mergeMap, switchMap usw. verwenden, um die innere Observable-Kette in die oberste Ebene zusammenzuflachen/zusammenzuführen. flatMap ist ein Alias ​​zu mergeMap, BTW.

export const getCurrentPositionEpic = action$ => 
    action$.ofType(GET_CURRENT_POSITION) 
    .mergeMap(() => getCurrentPosition$ 
     .flatMap((response) => Observable.of(
     getCurrentPositionFulfilled(response) 
    )) 
     .catch(error => Observable.of(getCurrentLocationRejected(error))) 
    ) 

Eine andere Sache - Sie brauchen nicht flatMap aka mergeMap zur Karte die getCurrentPosition$, um die getCurrentPositionFulfilled Aktion zu verwenden, da es 1 ist: 1. Du brauchst das nur, wenn es 1 zu viele ist.

export const getCurrentPositionEpic = action$ => 
    action$.ofType(GET_CURRENT_POSITION) 
    .mergeMap(() => getCurrentPosition$ 
     .map((response) => getCurrentPositionFulfilled(response)) 
     .catch(error => Observable.of(getCurrentLocationRejected(error))) 
    ) 

Es gibt keinen wirklichen Schaden darin Ihren Weg mit, aber es könnte andere, die den Code später halten verwirren.

Verwandte Themen