2017-05-02 45 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))) 
    ) 

有使用它自己的方式沒有真正傷害,但它可能會混淆別人誰以後維護的代碼。

相關問題