Ben*_*ins 3 rxjs react-native redux rxjs5 redux-observable
我试图使用原生的反应地理位置来getCurrentPosition,然后尽快返回的位置,使用反应天然地理编码器使用该位置得到的位置。我正在使用redux-observable史诗来完成所有这些。
这是我的两个史诗:
location.epic.js
import { updateRegion } from '../map/map.action'
import Geocoder from 'react-native-geocoder'
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)
.mergeMap(() =>
navigator.geolocation.getCurrentPosition(
(position) => Observable.of(
updateRegion(position),
getCurrentLocation(position)
),
error => Observable.of(getCurrentPositionRejected(error)),
{ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }
).do(x => console.log(x))
).do(x => console.log(x))
Run Code Online (Sandbox Code Playgroud)
一旦应用程序启动,此代码就会执行:
class Vepo extends Component {
componentDidMount() {
const { store } = this.context
this.unsubscribe = store.subscribe(() => { })
store.dispatch(fetchCategories())
store.dispatch(getCurrentPosition())
}
Run Code Online (Sandbox Code Playgroud)
fetchCategories()是一个也有史诗的动作,但这是有效的。调度getCurrentPosition()动作贯穿了上面的史诗。我能看到的唯一输出是我的减速器getLocationRejected()在控制台记录时处理:
there was an issue getting your current location: Error: invalid position: {lat, lng} required
at Object.geocodePosition (geocoder.js:15)
at MergeMapSubscriber.project (location.epic.js:17)
at MergeMapSubscriber._tryNext (mergeMap.js:120)
at MergeMapSubscriber._next (mergeMap.js:110)
at MergeMapSubscriber.Subscriber.next (Subscriber.js:89)
at FilterSubscriber._next (filter.js:88)
at FilterSubscriber.Subscriber.next (Subscriber.js:89)
at Subject.next (Subject.js:55)
at Object.dispatch (createEpicMiddleware.js:72)
at Object.dispatch (devTools.js:313)
Run Code Online (Sandbox Code Playgroud)
这是我的减速器:
const searchPage = (
initialLocationState = initialState.get('searchForm').get('location'),
action: Object): string => {
switch (action.type) {
case GET_CURRENT_LOCATION_FULFILLED: {
return action.payload
}
case GET_CURRENT_LOCATION_REJECTED: {
console.log('there was an issue getting your current location: ',
action.payload)
return initialLocationState
}
case GET_CURRENT_POSITION_REJECTED: {
console.log('there was an issue getting your current position: ',
action.payload)
return initialLocationState
}
default:
return initialLocationState
}
}
Run Code Online (Sandbox Code Playgroud)
有什么明显的我做错了吗?我尝试通过添加进行调试.do(x => console.log(x))没有任何作用,控制台没有记录任何内容。updateRegion()永远不会触发,因为它会分派一个动作并且减速器UPDATE_REGION永远不会执行。但是执行必须使它成为getCurrentPosition()例如的成功案例:
(position) => Observable.of(
updateRegion(position),
getCurrentLocation(position)
),
Run Code Online (Sandbox Code Playgroud)
必须执行,因为getCurrentLocation(position)确实被分派了。
我哪里错了?
在带有回调函数的函数上使用史诗的技术是什么?getCurrentPosition() 接受一个回调,回调处理负载。基本上,如果您从 getCurrentPosition() 中删除 Observable.of(,这就是正确使用 getCurrentPosition() 的方式 - 并且在没有 redux-observable 的情况下一直在为我工作。
在自定义 Observable 中包装任何东西都相当简单,与创建 Promise 非常相似,只是 Observables 是惰性的——理解这一点很重要!RxJS 文档
在地理定位的情况下,有两个主要的 API,getCurrentPosition和watchPosition. 它们具有相同的语义,除了watchPosition每次位置更改时都会调用您的成功回调,而不仅仅是一次。让我们使用它,因为将它建模为流/可观察对象是很自然的,而且是最灵活的。
function geolocationObservable(options) {
return new Observable(observer => {
// This function is called when someone subscribes.
const id = navigator.geolocation.watchPosition(
(position) => {
observer.next(position);
},
error => {
observer.error(error);
},
options
);
// Our teardown function. Will be called if they unsubscribe
return () => {
navigator.geolocation.clearWatch(id);
};
});
}
geolocationObservable({ enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 })
.subscribe(
position => console.log(position),
e => console.error(e)
);
// will log every time your location changes, until you unsubscribe
Run Code Online (Sandbox Code Playgroud)
由于它现在是一个 Observable,如果你只想要当前位置,你可以只做.take(1).
所以在你的史诗中使用它可能是这样的
// If you want, you could also use .share() to share a single
// underlying `watchPosition` subscription aka multicast, but
// that's outside the scope of the question so I don't include it
const currentPosition$ = geolocationObservable({
enableHighAccuracy: true,
timeout: 20000,
maximumAge: 1000
});
export const getCurrentPositionEpic = action$ =>
action$.ofType(GET_CURRENT_POSITION)
.mergeMap(() =>
currentPosition$
.take(1) // <----------------------------- only the current position
.mergeMap(position => Observable.of(
updateRegion(position),
getCurrentLocation(position)
))
.catch(error => Observable.of(
getCurrentPositionRejected(error)
))
);
Run Code Online (Sandbox Code Playgroud)
作为旁注,您可能不需要同时发送updateRegion()和getCurrentLocation()。您的减速器是否可以只监听单个动作,因为它们似乎都在发出相同的意图?
| 归档时间: |
|
| 查看次数: |
891 次 |
| 最近记录: |