代码之家  ›  专栏  ›  技术社区  ›  Seemax

Redux传奇行为模式

  •  0
  • Seemax  · 技术社区  · 7 年前

    这样的传奇故事非常成功:

    function* getPosition() {
      yield navigator.geolocation.getCurrentPosition(function(pos) {
        console.log(`I am getPosition: ${pos.coords.latitude}, ${pos.coords.longitude}`);
      });
    }
    

    但我需要Redux状态树中的坐标。因此,我尝试了几种模式,但都不起作用。 1) 无法将变量移出getCurrentPosition范围

    function* getPosition() {
      let position = {};
      yield navigator.geolocation.getCurrentPosition(function(pos) {
        position = pos;
      });
      // either
      console.log(`I am getPosition: ${position.coords.latitude}, ${position.coords.longitude}`);
      // or
      yield console.log(`I am getPosition: ${position.coords.latitude}, ${position.coords.longitude}`);
      // Any of two is undefined
    }
    

    2) 无法返回和赋值:

    function* getPosition() {
      const position = yield navigator.geolocation.getCurrentPosition(function(pos) {
        return pos;
      });
      yield console.log(`I am getPosition: ${position.coords.latitude}, ${position.coords.longitude}`);
    }
    

    3) 方法put无效:

    function* getPosition() {
      yield navigator.geolocation.getCurrentPosition(function(pos) {
        // Pos fetched
        console.log(`I am getPosition: ${pos.coords.latitude}, ${pos.coords.longitude}`);
        // Nothing happens. State is empty object.
        put({
          type: LOCATION_SET_POSITION,
          pos
        });
      });
    }
    

    locationReducer位于rootReducer的内部,其他工作减速机为:

    locationReducer.js
    export function locationReducer(state = {}, action) {
      switch (action.type) {
        case LOCATION_SET_POSITION:
          return action.pos
        default:
          return state;
      }
    }
    

    我没有actionCreater。据我所知, put 方法二者 调度操作并设置actionCreator。 如何将坐标放入状态树?

    1 回复  |  直到 6 年前
        1
  •  3
  •   alechill    7 年前

    你的问题是 geolocation.getCurrentPosition 是异步的,但采用了成功/错误回调样式,而您需要它作为向redux传奇提供信息的承诺

    function* getPositionSaga() {
        const getCurrentPosition = () => new Promise(
          (resolve, reject) => navigator.geolocation.getCurrentPosition(resolve, reject)
        )
        const pos = yield call(getCurrentPosition)
        yield put({type: LOCATION_SET_POSITION, pos})
    }
    

    这是我们的包装 getCurrentPosition 转换为返回 Promise<Position>

    call 是一种重复的传奇效果,如果给定的函数返回一个承诺,则只有在该承诺得到满足时才会产生,并将满足的值返回到传奇中以供进一步使用。

    put 是最终通过redux调度给定动作对象的效果

    任何redux saga效果都必须从生成器中产生,而不是直接调用,因为它们只为redux saga中间件执行器返回一个简单的指令对象(而不是立即实际执行副作用)。执行器只能在从生成器生成时访问和控制这些内容,因此在回调中使用它们(如示例3)不会像您期望的那样工作