2017-10-28 78 views
0

背景如何同步网页客户端和数据库?创建于客户端实体和处理标识

比方说,我试图保持项目的大名单,与Web UI提供了增加新的可能性。 我的架构是一个Web UI(React/Redux)+数据库/服务器(Graph.cool)。

现在当我添加一个新项目时,我可以做的就是简单地运行“创建”查询,取回带有其数据库ID的项目,并将项目存储在一个对象中,该项目通过ID索引所有项目。

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

问题

我需要一个解决方案,让我先在本地创建的项目,后来更换数据库ID本地ID当响应回来。 我该怎么做?

+0

原来这是鳕鱼的问题e组织/ Redux我有。请参阅下面的答案。现在我的问题不像我想的那么清楚/有用,我应该删除它吗? (或以某种方式改进它?) –

回答

1

最简单的方法是在对象上创建某种localKey字段,并按照惯例将其添加到您的商店。

只要后端完成处理并且事件进入,而不是将新对象添加到存储中,则使用localKey查找本地副本并将其替换。

0

原来,这是我的代码组织/ Redux的问题。

我无法弄清楚如何实现某种形式的解决方案就像砥Ø建议,因为:

  • 如果我率先打响请求我没有办法附上LOCALID并用它找回来响应跟踪它
  • 如果我在reducer中首先创建本地项目,我无法将localID传递给执行请求的部分,并存储从响应中提取的项目/我认为从一个减速器

我做了什么我nstead这似乎运作良好,是:

  • 大火,被在后台
  • 劳动者创造LOCALID并将其传递到两个新的行动拾起成为工人的第一个动作:一个用于创建本地用于发射的请求到数据库

这里的项目,一个是我的代码解决方案,与终极版+英雄传奇+纳基+经典的待办事项列表例如:

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); 
    } 
    } 
});