2017-07-08 3 views
1

Ich habe eine Anfrage Interceptor für Axios Anrufe. Es prüft mein jwt-Token und fordert bei Bedarf eine Aktualisierung an.Axios Request Interceptor warten bis Ajax Anruf

axios.interceptors.request.use((config) =>{ 

    const state = store.getState(); // get renewed state 
    const time = Math.floor(new Date().getTime()/1000); 

    if( 
     ! state.app.jwtRefreshOnRequest 
     && time >= state.jwt.expires - 120 
     && state.jwt.refresh_before > time 
    ){ // expiring in 2 min. refresh  

     //dispatch({type: 'JWT_REFRESH_REQUEST'}); 
     axios.get(API_BASE_URL + '/auth/refresh') 
      .then(function(response){ 
       // dispatch({type: 'JWT_REFRESH_SUCCESS', payload: response.data}); 
       axios(config).then(resolve, reject); 
      }) 
      .catch(function(err){    
       reject(err); 
     }); 

    }  

    return config; 
}); 

Dieser Code ruft die Refresh richtig und speichert die neuen Token, aber der ursprüngliche Anruf nicht hält nicht, bis die Abfangjäger Anfrage erfolgt, so dass die abgelaufenen Token verwendet werden.

Also, ich denke, ich muss einen synchronen Aufruf von Interceptor machen.

Antwort

7

Vermeiden Sie synchrone Aufrufe für HTTP-Anforderungen, da diese Ihre Anwendung nur zum Absturz bringen.

Was Sie hier tun müssen, ist den aufrufenden Code asynchron zu machen - die allgemeine Regel mit allem Callback, Versprechen oder async verwandt ist, dass, sobald Sie asynchron sind, alles async sein muss.

Hier gibt axios.get eine Promise zurück - ein Objekt, das die asynchrone HTTP-Anfrage verfolgt und nach dem Abschluss auflöst. Sie müssen das anstelle der config zurückgeben.

Wir tun das, indem wir eine neue Promise zurückgeben - wenn eine HTTP-Anfrage für ein neues Token erforderlich ist, wartet es darauf, wenn nein kann es resolve sofort.

axios.interceptors.request.use(config => 
    new Promise((resolve, reject) => { 
     // ... your code ... 

     axios.get(API_BASE_URL + '/auth/refresh') 
      .then(response => { 
       // Get your config from the response 
       const newConfig = getConfigFromResponse(response); 

       // Resolve the promise 
       resolve(newConfig); 
      }, reject); 

     // Or when you don't need an HTTP request just resolve 
     resolve(config); 
    }) 
}); 

Jedes Mal, wenn Sie sehen, dass then Sie mit Promise es zu tun, und wenn Sie alles sind ein Promise zurückgeben muss.

Dies ist viel einfacher, wenn Sie async/await verwenden können - neue Keywords unterstützt von modernen Browsern und transpilable wenn Sie ältere Benutzer unterstützen müssen. Mit diesen können Sie einfach den Promise Aufruf inline mit dem Schlüssel await setzen.

axios.interceptors.request.use(async config => 

    // ... your code ... 

    if(/* We need to get the async token */) { 
     const response = await axios.get(API_BASE_URL + '/auth/refresh'); 
     config = getConfigFromResponse(response); 
    } 

    return config; 
}); 
+1

Danke, es hat funktioniert. Ich habe viel von deiner Antwort gelernt :) – Sisir