2016-05-18 26 views
5

Voglio modellare la seguente logica asincrona utilizzando Redux:Dove devo scrivere flussi asincroni complessi in Redux?

  1. Azione utente innesca una catena di chiamate asincrone API.
  2. Qualsiasi chiamata API potrebbe restituire 401 di stato (login scaduta)
  3. Se API risponde con 401, schermo a comparsa
  4. On successo ri-login, chiamata API ristampa e ri-login continuano

I non sono sicuro di dove mettere questa logica. Le azioni non conoscono altre azioni, hanno solo accesso alla spedizione, quindi non possono fermarsi e aspettare che vengano completate. I riduttori non hanno accesso alla spedizione, quindi non posso metterlo lì ... quindi dove vive? Middleware personalizzato? store.listen? In un componente intelligente?

Attualmente sto usando il middleware redux-promise-& redux-thunk. Come sarebbe meglio organizzare questo tipo di flusso - senza richiedere il buy-in in qualcosa come redux-saga o redux-rx, ecc.?

Inoltre non è sicuro il modo migliore per interrompere in modo trasparente la chiamata API per eseguire quelle altre azioni, ad esempio la chiamata API non dovrebbe attivare le azioni completate o non riuscite fino a dopo il completamento del processo di accesso opzionale.

risposta

1

Mi sembra che tu voglia un creatore di azioni che generi un Thunk e mantenga tutta quella logica nel Thunk. Non c'è davvero nessun altro buon modo per preservare l'associazione tra la tua suite di chiamate API e garantire che tutti gli altri vengano cancellati se uno fallisce.

  1. In questo Thunk, devi sparare le chiamate API, e raccogliere le loro promesse:

    const call1 = promiseGenerator1(); 
    const call2 = promiseGenerator2(); 
    const call3 = promiseGenerator3(); 
    const allCallPromises = [call1, call2, call3]; 
    
  2. utilizzare un gestore di all() promessa di seguire da loro:

    const watcher = Promise.all(allCallPromises).then(allSuccess, anyFail); 
    
  3. tuo fail handler:

    • annulla il resto delle promesse se qualcuno di loro è di 401. (Si noti, questo richiede una libreria come Bluebird che ha la semantica di cancellazione, o qualche altra forma di aumento della vostra promessa/richiesta.)
    • spedizione un'azione o una rotta cambiamento per innescare la ri-effettuare il login finestra

      anyFail(error) => { 
          if (error.status === 401) { 
           allCallPromises.forEach((item)=> {item.cancel();}); 
           reLogin(); 
          } 
      } 
      
  4. Quindi, sarei propenso a lasciare che il componente relogin si preoccupi di ripetere nuovamente la stessa azione complessa per emettere tutte le chiamate.

  5. Tuttavia, se la suite di chiamate API è in qualche modo variabile o specifica del contesto, è possibile memorizzare nella cache nello store quelle necessarie, all'interno del gestore anyFail. Avere un riduttore in cui è possibile memorizzare un actionPendingReLogin. Comporre un'azione che si ri-fuoco le stesse chiamate come l'ultima volta, e poi spedirlo:

    dispatch(createAction('CACHE_RELOGIN_ACTION`, actionObjectToSaveForLater)); 
    

    (Oppure, semplicemente cache di qualsiasi azione-creatore si è utilizzato.)

    Poi, seguendo nuovo login di successo, è possibile:

    const action = store.getState('actionPendingReLogin'); 
    dispatch(action); 
    // or: 
    const actionCreator = store.getState('actionPendingReLogin'); 
    dispatch(actionCreator()); 
    

Oh: e nel tuo allSuccess gestore si sarebbe semplicemente la spedizione i risultati delle chiamate asincrone.