2017-10-28 2 views
0

HintergrundWie synchronisiert man den Webclient und die Datenbank? Erstellen Einheit auf Client-Seite und mit IDs Umgang

Sagen wir, ich bin versucht, eine große Liste von Gegenständen zu halten, mit einem Web-UI die Möglichkeit bietet, neue hinzuzufügen. Meine Architektur ist eine Web-Benutzeroberfläche (React/Redux) + eine Datenbank/Server (Graph.cool).

Jetzt, wenn ich ein neues Element hinzufügen, was ich tun kann, ist einfach führen Sie die "erstellen" Abfrage, zurück das Element mit seiner Datenbank-ID, und speichern Sie das Element in einem Objekt, das alle Elemente nach ID indiziert.

Problem: Das Netzwerk ist möglicherweise langsam/offline, die Anfrage kann fehlschlagen, und ich möchte immer noch in der Lage sein, dem Benutzer sofort sein neu erstelltes Element in der Liste anzuzeigen und später mit der Datenbank zu synchronisieren.

Frage

ich eine Lösung brauchen würde, die mir das Element zuerst lokal erstellen können, und ersetzen Sie später die lokale ID mit der ID-Datenbank, wenn die Antwort zurückkommt. Wie kann ich das tun?

+0

Stellt sich heraus, es war ein Problem der Kabeljau Die Organisation/Redux, die ich hatte. Siehe meine Antwort unten. Jetzt fühlt sich meine Frage nicht so klar/nützlich an, wie ich es beabsichtigt habe, sollte ich sie löschen? (oder verbessern Sie es irgendwie?) –

Antwort

1

Der einfachste Weg wäre, eine Art localKey Feld auf dem Objekt zu erstellen, und fügen Sie es wie gewohnt zu Ihrem Geschäft hinzu.

Immer wenn das Backend die Verarbeitung abschließt und das Ereignis eingeht, verwenden Sie localKey, um das neue Objekt zum Speicher hinzuzufügen, um die lokale Kopie zu finden und sie zu ersetzen.

0

Es stellte sich heraus, es war ein Problem der Code-Organisation/Redux, die ich hatte.

Ich konnte nicht herausfinden, wie eine Art von Lösung zu implementieren, wie Tobe O vorgeschlagen, weil:

  • Wenn ich die Anfrage zuerst gefeuert ich keine Möglichkeit hatte, um den localId zu befestigen und wieder mit der get Antwort, um es zu verfolgen
  • Wenn ich das lokale Element zuerst in einem Reducer erstellt habe, konnte ich die localID nicht an den Teil übergeben, der die Anfrage ausführt, und speichert das aus der Antwort extrahierte Element/Ich denke, es ist eine schlechte Übung, Aktionen von einem zu werfen Reduzierstück

Was ich tat ich nstead, die gut zu funktionieren scheint, ist:

  • Feuer eine erste Aktion, die
  • von einem Arbeiter oben im Hintergrund aufgenommen wird
  • der Arbeiter den localId schafft und übergibt sie an zwei neue Aktionen: eine für die lokale Erstellung Artikel und ein für die Anforderung an die Datenbank

Hier sind meine Lösung in Code, mit Redux + Sagas + Kea + klassischem toDo-Liste Beispiel Brennen:

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