Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 如何同步web客户端和数据库?在客户端创建实体并处理ID_Database_Redux_Synchronization - Fatal编程技术网

Database 如何同步web客户端和数据库?在客户端创建实体并处理ID

Database 如何同步web客户端和数据库?在客户端创建实体并处理ID,database,redux,synchronization,Database,Redux,Synchronization,背景 比如说,我正试图保留一个大的项目列表,其中一个web UI提供了添加新项目的可能性。 我的体系结构是一个web UI React/Redux+一个数据库/服务器图 现在,当我添加一个新项时,我所能做的就是运行create查询,用它的数据库ID返回该项,并将该项存储在一个对象中,该对象按ID索引所有项 问题:网络可能很慢/离线,请求可能会失败,我仍然希望能够立即向用户显示列表中新创建的项目,并稍后与数据库同步 问题: 我需要一个解决方案,允许我首先在本地创建项,然后在响应返回时用数据库ID替

背景

比如说,我正试图保留一个大的项目列表,其中一个web UI提供了添加新项目的可能性。 我的体系结构是一个web UI React/Redux+一个数据库/服务器图

现在,当我添加一个新项时,我所能做的就是运行create查询,用它的数据库ID返回该项,并将该项存储在一个对象中,该对象按ID索引所有项

问题:网络可能很慢/离线,请求可能会失败,我仍然希望能够立即向用户显示列表中新创建的项目,并稍后与数据库同步

问题:

我需要一个解决方案,允许我首先在本地创建项,然后在响应返回时用数据库ID替换本地ID。
我该怎么做呢?

最简单的方法是在对象上创建某种localKey字段,然后像往常一样将其添加到存储中


每当后端完成处理并出现事件时,使用localKey查找本地副本并替换它,而不是将新对象添加到存储中。

结果表明,这是我遇到的代码组织/Redux问题

我不知道如何实施Tobe O建议的某种解决方案,因为:

如果我先触发请求,我就无法附加localID并将其与跟踪它的响应一起取回 如果我首先在reducer中创建了本地项,我就无法将localID传递给执行请求并存储从响应中提取的项的部件/我认为从reducer中抛出操作是不好的做法 我所做的似乎效果不错的是:

触发由后台工作人员拾取的第一个动作 worker创建localID并将其传递给两个新操作:一个用于创建本地项,另一个用于向数据库触发请求 下面是我的代码解决方案,Redux+Sagas+Kea+是一个经典的待办事项列表示例:

export default kea({
  path: () => ["kea", "taskStore"],
  actions: () => ({
    addTask: title => ({ title }),
    storeLocalTask: (localId, title) => ({ localId, title }),
    storeDBTask: (localId, task) => ({ localId, task }),
    setTasks: tasks => ({ tasks }),
    fetchTasks: () => ({})
  }),
  *start() {
    const { fetchTasks } = this.actions;
    yield put(fetchTasks());
  },
  reducers: ({ actions }) => ({
    indexedTasks: [
      {},
      PropTypes.object,
      {
        [actions.setTasks]: (state, payload) => indexById(payload.tasks),
        [actions.storeLocalTask]: (state, payload) => {
          const { localId, title } = payload;
          return { ...state, [localId]: { localId, title } };
        },
        [actions.storeDBTask]: (state, payload) => {
          const { localId, task } = payload;
          const { [localId]: _dispose_, ...rest } = state;
          return { ...rest, [task.id]: task };
        }
      }
    ]
  }),
  takeLatest: ({ actions, workers }) => ({
    [actions.fetchTasks]: workers.fetchTasks,
    [actions.addTask]: workers.createTask
  }),
  workers: {
    *fetchTasks() {
      const res = yield db.query({
        query: gql`
          query {
            allTasks {
              id
              title
            }
          }
        `
      });
      const { setTasks } = this.actions;
      yield put(setTasks(res.data.allTasks));
      yield delay(1000);
    },
    *createTask(action) {
      const { storeLocalTask, storeDBTask } = this.actions;
      const { title } = action.payload;
      const localId = randomString();
      yield put(storeLocalTask(localId, title));

      const res = yield db.mutate({
        mutation: gql`
          mutation($title: String!) {
            createTask(title: $title) {
              id
              title
            }
          }
        `,
        variables: { ...action.payload }
      });
      yield put(storeDBTask(localId, res.data.createTask));
      yield delay(1000);
    }
  }
});

事实证明,这是我遇到的代码组织/重复使用问题。见下面我的答案。现在我的问题不像我想的那么清楚/有用,我应该删除它吗?或者以某种方式改进它?