【求助】redux-saga调用geolocation好像掉进call back hell了~

#1

网页app需要调用设备的gps定位,使用redux + saga
直接上代码
saga 文件里相关但是不会错的代码

export function* getLocation(){
  可能出错的地方,详细的代码在下面。
}

export function* getLocationWatcher() {
  while (yield take(GET_GEO_LOCATION)) {
    yield call(getLocation);
  }
}

export function* homeSaga() {
  const watcher = yield fork(getLocationWatcher);

  yield take(LOCATION_CHANGE);
  yield cancel(watcher);
}

export default [
  homeSaga,
];

可能错误产生的地方

import {getGeoLocationSuccess} from './actions'

 export function onSuccess(position) {
  put(getGeoLocationSuccess([position.coords.latitude, position.coords.longitude]))
  console.log([position.coords.latitude, position.coords.longitude])
}
export function onError(error) {
  switch (error.code) {
    case error.PERMISSION_DENIED:
      return "用户拒绝对获取地理位置的请求。"
      break;
    case error.POSITION_UNAVAILABLE:
      return "位置信息是不可用的。"
      break;
    case error.TIMEOUT:
      return "请求用户地理位置超时。"
      break;
    case error.UNKNOWN_ERROR:
      return "未知错误。"
      break;
  }
}
export function* getLocation() {

  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(onSuccess,onError);
  }
  else {
    yield put((getGeoLocationError(showError)))
  }

}

症状表述
log能正确输出coords是一个array,但是put(action)的操作没能成功更新state
猜测:问题的原因可能在于 saga使用了generator put的操作应该与之相关,navigator.geolocation.getCurrentLocation(calll back 函数)有冲突?操作不当?对generator和回调研究不深,求救!!

#2

首先,要把getCurrentPosition()改成promise.

function getCurrentPosition() {
    return new Promise((resolve, reject) =>
        navigator.geolocation.getCurrentPosition(resolve, reject));
}

然后要在getLocation改成

function* getLocation() {
  try {
    const position = yield call(getCurrentPosition);
    yield call(onSuccess, position);
  } catch (e) {
    onError(e);
  }
}

最后,好像在getLocationWeather里面,yield call(getLocation) 要改成 yield* getLocation()
因为getLocation不是function而是generator函数