2017-05-02 44 views
2

当我在下面的代码中注释getCurrentPositionEpic时,该应用程序有效。但是,如果我离开它注释掉我得到的错误:redux-observable操作必须是普通对象。使用自定义中间件进行异步操作

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))) 
    ) 

下面的代码只是用来转换一个辅助反应本地navigator.geolocation.getCurrentPosition到可观察而不是回调函数。

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) 
    }) 

什么引起的错误?

试图通过在商店:

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))) 
} 
) 

使用https://github.com/devfd/react-native-geocoderGeocoder.geocodePosition

回答

3

的问题是你的mapTo使用。你基本上是在说“把这个动作映射到一个可观察对象”,所以现在你的史诗可以返回一个可观察的可观察动作,而不仅仅是一个可观察到的动作。

换言之,您的史诗正在发射Observables,而不是发射动作。您需要使用像mergeMap,switchMap等合并策略运算符来合并,以将内部Observable链平铺/合并到顶层。 flatMapmergeMap的别名,顺便说一句。其他

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

一两件事 - 你不需要使用flatMap又名mergeMap映射getCurrentPosition$getCurrentPositionFulfilled行动,因为它是1:1。你只需要,如果它是1到很多。

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

有使用它自己的方式没有真正伤害,但它可能会混淆别人谁以后维护的代码。

相关问题