将传奇选择效果包装到一个Promise中,以模拟数据库查询Promise

时间:2019-07-09 14:20:42

标签: javascript redux-saga

我需要将大量代码从服务器传输到客户端。

在服务器上,该代码执行大量的数据库查询承诺。

在react / redux客户端上,我想将yield select(state => ...)包装到Promise中以模拟代码的数据库调用。

将内容尝试为

      return new Promise(function* (res, rej) {
        const val = yield select(state => state.user.app.email);
        res(val);
      });

但是根本不工作。

我希望诺言在找到期望值时解决。

非常感谢

1 个答案:

答案 0 :(得分:0)

找到了一种解决方法,试图进行解释(对不起,我对此不甚了解)。

  • “发电机上下文”是从redux“调度”启动的。
  • 在“生成器上下文”中,可以很容易地调用promise并等待解决。
  • 但是从从“生成器上下文”发起的承诺中,无法启动“本地”生成器上下文。

然后所有的事情就是找到一种从诺言中重新进入“生成器上下文”的方法。

技巧如下:

  • 承诺:
    • 获取promiseId
    • 将带有PromiseId的记录保存在数组中,然后解决并拒绝。
    • 调度redux事件。
  • 在生成器上下文中处理事件,然后可以使用yield select提取适当的值。
  • 一旦获得值,它将调用通用解析,该通用解析在数组中找到记录并解析承诺。

这是一个例子

// In generator context:

const effects = {
  *MAIN_ENTRY_POINT({ data, internal }) {
    // call a complex process that will use many promises to get data.
    const resp = yield sagas.call(ptaFunctions.complexProcess);
  },
  *ALU_QUERY(payload) {
    // back in generator context
    // the ALU_QUERY event is processed 
    // it calls a generator function to get the value (here: getUserEmail)

    const { fn, promiseId } = payload;
    const resp = yield sagas.call(ptaFunctions[fn], payload);
    // then it calls the "generic" resolve, which will find the appropriate promise record
    ptaResolve({ promiseId, resp });
  }
};

export const ptaFunctions = {
  complexProcess: async () => {
    // complex process wants the user email through a promise
    return await ptaFunctions.promiseGetUserEmail();
  },
  *getUserEmail() {
    // the select saga is available here
    return yield sagas.select(state => state.user.app.email);
  },
  promiseGetUserEmail() {
    // create the promise to get the user email. first get an Id
    const promiseId = uuidBase62.v4();
    return new Promise((resolve, reject) => {
      // save the promise in a record
      promisesStack.push({ promiseId, resolve, reject });
      // push a redux event ALU_QUERY for that
      globalDispatch({
        type: "ALU_QUERY",
        fn: "getUserEmail",
        promiseId
      });
    });
  }
};

export const ptaResolve = ({ promiseId, resp }) => {
  // call the resolve function of the appropriate promise
  const rec = _.head(_.remove(promisesStack, r => r.promiseId === promiseId));
  rec.resolve(resp);
};

这样做,我可以在完全不了解效果的代码上使用效果