Come strutturare una risposta API REST per un frontend Flux / Redux?

1

Ho una domanda su come strutturare una risposta in cui restituisco oggetti relativi ad altri oggetti (uno-a-molti / molti-a-uno) e a dirmi se il modo in cui ho strutturato i miei endpoint è sbagliato o no, o se c'è un modo migliore.

Il mio scenario: Ho un'app JS costruita su Flux dove ho questi negozi: - Riunioni - Utenti

Per semplicità, diciamo che l'utente finale è un gestore di riunioni e desidera vedere una tabella / elenco di tutte le riunioni e ogni riga visualizzerà la descrizione e la data della riunione, oltre ai nomi, alle e-mail e ai partecipanti telefoni.

Quindi, a caricamento della pagina, faccio una richiesta alla rotta / riunioni che restituisce un oggetto come questo:

{
    meetings: [
        {id: 1, date: '2016-01-01', attendees: [1, 2, 3]},
        {id: 2, date: '2016-01-02', attendees: [2, 3, 4]},
    ],
    allUsersIntersectedByMeetings: [
        {1, name: 'a', phone: '1800-01111'},
        {2, name: 'b', phone: '1800-02222'},
        {3, name: 'c', phone: '1800-03333'},
        {4, name: 'd', phone: '1800-04444'},
    ]
}

Se si nota, ho separato i dati degli utenti dall'array delle riunioni, questo è per compattare il risultato e impedire l'invio di informazioni duplicate sullo stesso utente (nel mio esempio i dati dell'utente sono piuttosto piccoli, ma nella vita reale lì potrebbero essere molte colonne sulla tabella utente).

Il motivo per cui ho disaccoppiato le riunioni e gli utenti, è che non voglio restituire tonnellate di dati duplicati, perché nella vita reale tratterò almeno cento riunioni in una richiesta e gli utenti potrebbero ripetere molte volte attraverso diversi incontri.

Quindi con questa struttura, metto tutti i clienti nel mio flux store front-end 'Users', e manterrò tutti i miei dati in sincronia. Esempio: se volessi modificare il telefono di un utente, lo farò direttamente nell'archivio degli utenti e questo si propagherà attraverso l'interfaccia utente dove altri incontri fanno riferimento allo stesso utente. Non devo assolutamente toccare gli oggetti della riunione.

Inoltre, potrei incorrere in un problema in cui dovrei anche restituire dati nidificati sugli utenti, come le informazioni sulla loro società:

{userId: 1, name: 'a', phone: '1800-0111', email: '[email protected]', companyId: 10}

{companyId: 10, phone: '1900-02222', name: 'ACME INC'}.

Pensi che mi stia preoccupando troppo della larghezza di banda della rete? Dovrei semplicemente restituire le riunioni con i dati degli utenti popolati (ala 'MongoDB)?.

O dovrei semplicemente restituire le riunioni ed eseguire una richiesta separata per recuperare utenti unici sotto endpoint API degli utenti come '/ users? filterById = 1,2,3'? Anche se mi piace questo approccio, sarei preoccupato per la velocità, se per esempio lascio che l'utente finale cerchi le riunioni su una casella di input e su ogni evento di modifica dell'ingresso aggiorni i risultati (come una ricerca elastica). Penso che i risultati si sentirebbero molto lenti a comparire se mi venisse richiesto di mostrare le informazioni dei suoi utenti allo stesso tempo. Pensieri?

Esiste un modo de facto per risolvere questi problemi con REST? Quali sarebbero i tuoi suggerimenti?

Grazie.

    
posta Oscar Balladares 27.06.2016 - 02:00
fonte

2 risposte

0

Non conosco Flux, e la mia risposta è "dipende".

Modifica con sommario : sceglierei tra (A) incluso il resrouce del partecipante direttamente sotto le riunioni (e non ottimizzando come hai fatto), o (B) non li includi affatto e fornisci solo URI delle risorse dei partecipanti. La scelta (A) è un ragionevole compromesso ai miei occhi.

Se stai cercando di essere il più possibile RESTful, incluse due risorse di primo livello ( meetings e allUsersIntersectedByMeetings ) non si adattano bene.

Al contrario, potresti avere la tua /meetings raccolta di riunioni responsabile della restituzione delle riunioni. Un modo forse non efficiente della rete è di aggiungere collegamenti da una risorsa meeting all'URL di ciascuno dei suoi partecipanti.

È quindi possibile che il browser memorizzi nella cache i partecipanti (persone) che ha già richiesto in passato.

Invece di collegamenti, puoi includere direttamente gli oggetti partecipanti, come:

{ "meetings": [ { "id": 1, "attendees": [ { "id": 1, "name": "Oscar" } ] ] }

A proposito, lo standard "API JSON" utilizza una sezione includes come il tuo esempio originale. Non sono sicuro di quanto RESTful o non sia questo approccio.

    
risposta data 28.06.2016 - 10:15
fonte
1

Un buon argomento per normalizzare o appiattire i dati annidati è quando si tratta di aggiornare questi dati. Questo è ben spiegato qui . Poiché questo è un caso d'uso comune, Dan Abramov ha creato normalizr , successivamente riscritto e ora mantenuto da Paul Armstrong.

Ma se si controlla anche l'API e probabilmente si archiviano i dati in forma normalizzata nel database, è piuttosto sciocco de-normalizzarlo nel proprio endpoint API solo per normalizzarlo subito dopo nel client (usando normalizr). .. In tal caso, sicuramente se sei l'unico consumatore, lascia i dati normalizzati e passali sul cavo al tuo cliente in quel modo.

Concretamente avresti qualcosa di simile

GET /meetings

{
    "result": ["1", "2"],
    "entities": {
        "meetings": {
            "1": { "id": 1, "date": "2016-01-01", "attendees": [1, 2, 3] },
            "2": { "id": 2, "date": "2016-01-02", "attendees": [2, 3, 4] }
        },
        "users": {
            "1": { "id": 1, "name": "User 1" },
            "2": { "id": 2, "name": "User 2" },
            "3": { "id": 3, "name": "User 3" },
            "4": { "id": 4, "name": "User 4" }
        }
    }
}

Tale risposta è molto semplice da incorporare nel tuo negozio in modo generico.

Se hai più consumatori, puoi optare per un parametro di query normalize=true . Potresti anche voler combinare questo con un qualche tipo di parametro di query expand|include=entities,to,include .

Infine, tieni presente che la specifica dell'API JSON non funziona bene con struttura normalizzata dei negozi flux / redux.

Ulteriori letture:

risposta data 10.10.2017 - 14:33
fonte

Leggi altre domande sui tag