rxjs

2016-01-20 24 views
38

का उपयोग करके रीफ्रेश टोकन हैंडलिंग करें क्योंकि मैंने कोणीय 2 से शुरू किया है। मैंने अपनी सेवाओं को टी के पर्यवेक्षण के लिए सेट अप किया है। सेवा में मेरे पास नक्शा() कॉल होगा, और इन सेवाओं का उपयोग करने वाले घटक केवल सदस्यता() से उपयोग करेंगे प्रतिक्रिया के लिए प्रतीक्षा करें। इन साधारण परिदृश्यों के लिए मुझे वास्तव में rxjs में खोदने की ज़रूरत नहीं थी, इसलिए सब ठीक था।rxjs

अब मैं निम्नलिखित प्राप्त करना चाहता हूं: मैं ताज़ा टोकन के साथ Oauth2 प्रमाणीकरण का उपयोग कर रहा हूं। मैं एक एपीआई सेवा बनाना चाहता हूं जो अन्य सभी सेवाओं का उपयोग करेगी, और 401 त्रुटि लौटाए जाने पर रीफ्रेश टोकन को पारदर्शी रूप से संभाल लेंगे। तो, 401 के मामले में, मैं पहले ओएथ 2 एंडपॉइंट से एक नया टोकन लाता हूं, और फिर नए टोकन के साथ अपना अनुरोध पुनः प्रयास करता हूं।

request(url: string, request: RequestOptionsArgs): Promise<Response> { 
    var me = this; 

    request.headers = request.headers || new Headers(); 
    var isSecureCall: boolean = true; //url.toLowerCase().startsWith('https://'); 
    if (isSecureCall === true) { 
     me.authService.setAuthorizationHeader(request.headers); 
    } 
    request.headers.append('Content-Type', 'application/json'); 
    request.headers.append('Accept', 'application/json'); 

    return this.http.request(url, request).toPromise() 
     .catch(initialError => { 
      if (initialError && initialError.status === 401 && isSecureCall === true) { 
       // token might be expired, try to refresh token. 
       return me.authService.refreshAuthentication().then((authenticationResult:AuthenticationResult) => { 
        if (authenticationResult.IsAuthenticated == true) { 
         // retry with new token 
         me.authService.setAuthorizationHeader(request.headers); 
         return this.http.request(url, request).toPromise(); 
        } 
        return <any>Promise.reject(initialError); 
       }); 
      } 
      else { 
       return <any>Promise.reject(initialError); 
      } 
     }); 
} 

कोड में ऊपर, authService.refreshAuthentication() नया टोकन लाने और localStorage में संग्रहीत होगा: नीचे कोड वह ठीक वादों से काम करता है, है। authService.setAuthorizationHeader पहले से अपडेट किए गए टोकन में 'प्राधिकरण' शीर्षलेख सेट करेगा। यदि आप कैच विधि को देखते हैं, तो आप देखेंगे कि यह एक वादा (रीफ्रेश टोकन के लिए) देता है कि इसके बदले में अंततः एक और वादा (अनुरोध की वास्तविक दूसरी कोशिश के लिए) वापस आ जाएगा।

मैं वादों का सहारा के बिना यह कर करने का प्रयास किया:

request(url: string, request: RequestOptionsArgs): Observable<Response> { 
    var me = this; 

    request.headers = request.headers || new Headers(); 
    var isSecureCall: boolean = true; //url.toLowerCase().startsWith('https://'); 
    if (isSecureCall === true) { 
     me.authService.setAuthorizationHeader(request.headers); 
    } 
    request.headers.append('Content-Type', 'application/json'); 
    request.headers.append('Accept', 'application/json'); 

    return this.http.request(url, request) 
     .catch(initialError => { 
      if (initialError && initialError.status === 401 && isSecureCall === true) { 
       // token might be expired, try to refresh token 
       return me.authService.refreshAuthenticationObservable().map((authenticationResult:AuthenticationResult) => { 
        if (authenticationResult.IsAuthenticated == true) { 
         // retry with new token 
         me.authService.setAuthorizationHeader(request.headers); 
         return this.http.request(url, request); 
        } 
        return Observable.throw(initialError); 
       }); 
      } 
      else { 
       return Observable.throw(initialError); 
      } 
     }); 
} 

कोड ऊपर मैं क्या उम्मीद भी नहीं करता है: एक 200 प्रतिक्रिया के मामले में, यह ठीक से प्रतिक्रिया देता है। हालांकि, अगर यह 401 को पकड़ता है, तो यह सफलतापूर्वक नया टोकन पुनर्प्राप्त करेगा, लेकिन सब्सक्राइब विल अंततः प्रतिक्रिया के बजाय एक अवलोकन योग्य पुनर्प्राप्त करेगा। मुझे लगता है कि यह अप्रत्याशित वेधशाला है जिसे पुनः प्रयास करना चाहिए।

मुझे एहसास है कि आरएक्सजेएस लाइब्रेरी पर काम करने का वादा तरीका अनुवाद करना संभवतः जाने का सबसे अच्छा तरीका नहीं है, लेकिन मैं "सबकुछ एक धारा है" समझने में सक्षम हूं। मैंने फ्लैटमैप से जुड़े कुछ अन्य समाधानों की कोशिश की है, फिर से प्रयास करें ... लेकिन दूर नहीं गए, इसलिए कुछ मदद की सराहना की गई।

उत्तर

22

अपने कोड पर एक त्वरित नज़र से मैं कहूंगा कि आपकी समस्या यह प्रतीत होती है कि आप Observable को फ़्लैटन नहीं कर रहे हैं जो refresh सेवा से वापस आ गया है।

catch ऑपरेटर को उम्मीद है कि आप एक Observable कि यह विफल रहा है नमूदार के अंत पर जोड़ जाएगा ताकि नीचे धारा Observer अंतर पता नहीं है वापस आ जाएगी।

गैर -401 मामले में आप एक अवलोकनयोग्य लौटकर यह सही तरीके से कर रहे हैं जो प्रारंभिक त्रुटि को पुनर्स्थापित करता है। हालांकि ताज़ा स्थिति में आप Observable लौट रहे हैं, एकल मूल्यों के बजाय अधिकObservables उत्पन्न करता है।

मैं तुम्हें ताज़ा तर्क बदल होने के लिए सुझाव है:

return me.authService 
      .refreshAuthenticationObservable() 
      //Use flatMap instead of map 
      .flatMap((authenticationResult:AuthenticationResult) => { 
        if (authenticationResult.IsAuthenticated == true) { 
        // retry with new token 
        me.authService.setAuthorizationHeader(request.headers); 
        return this.http.request(url, request); 
        } 
        return Observable.throw(initialError); 
    }); 

flatMap एक भी धारा में मध्यवर्ती Observables परिवर्तित कर देंगे।

+0

हा, यह काम करता है :) मैंने flatMap विधि का उपयोग करने का प्रयास किया है, लेकिन स्पष्ट रूप से सही तरीके से नहीं। थेंक्स पॉल! Ps: मुझे rxjs में काफी गन्दा लगता है कि वे इन विधियों को विभिन्न नामों वाली फ़ाइलों में छिपाने के लिए प्रवृत्त होते हैं। काम करने के लिए flatMap विधि के लिए, मुझे "mergeMap" फ़ाइल आयात करना पड़ा ... – Davy

+0

@ डेवी मई मैं पूछ सकता हूं कि आप किस संस्करण का उपयोग कर रहे हैं? यदि यह ReactiveX से प्रोजेक्ट है, तो यह अभी भी बीटा में है, इसलिए दस्तावेज़ीकरण अभी भी कम कमी है जबकि सभी कार्यक्षमता पूरी हो रही है। – paulpdaniels

+0

यह एक: https://github.com/ReactiveX/RxJS ("आरएक्सजेएस" एनपीएम पैकेज)। – Davy

9

आरएक्सजेएस की नवीनतम रिलीज में, flatMap ऑपरेटर का नाम बदलकर mergeMap कर दिया गया है।

संबंधित मुद्दे