RxJS मैप ऑपरेटर (कोणीय) से त्रुटि कैसे फेंकें


93

मैं एक शर्त के आधार पर अपने अवलोकन योग्य मानचित्र ऑपरेटर से एक त्रुटि फेंकना चाहता हूं । उदाहरण के लिए यदि सही एपीआई डेटा प्राप्त नहीं हुआ है। कृपया निम्नलिखित कोड देखें:

private userAuthenticate( email: string, password: string ) {
    return this.httpPost(`${this.baseApiUrl}/auth?format=json&provider=login`, {userName: email, password: password})
        .map( res => { 
            if ( res.bearerToken ) {
                return this.saveJwt(res.bearerToken); 
            } else {
                // THIS DOESN'T THROW ERROR --------------------
                return Observable.throw('Valid token not returned');
            }
        })
        .catch( err => Observable.throw(this.logError(err) )
        .finally( () => console.log("Authentication done.") );
}

मूल रूप से जैसा कि आप कोड में देख सकते हैं, यदि प्रतिक्रिया (रेस ऑब्जेक्ट) में 'बियररोकैन' नहीं है, तो मैं एक त्रुटि फेंकना चाहता हूं। ताकि मेरी सदस्यता में यह नीचे दिए गए 2 पैरामीटर (हैंडलएयर्रम) में चला जाए।

.subscribe(success, handleError)

कोई सुझाव?


4
किस बारे में throw 'Valid token not returned';?
गुंटर ज़ोचबॉयर

संकलन करने में विफल
हसन

सटीक त्रुटि संदेश कृपया।
गुंटर ज़ोचबॉयर

2
क्षमा करें, यह return throw 'message here'बिना returnकीवर्ड के काम नहीं करता है । अगर इसकी तार्किक रूप से सही है तो मुझे जांचने दें।
हसन

त्रुटि पाठ subscribeविधि में प्राप्त नहीं किया जा रहा है और .finally()स्ट्रीम में भी ट्रिगर होता है। (हालाँकि निष्पादन रोक दिया गया है जो एक अच्छी बात है)
हसन

जवाबों:


141

बस map()ऑपरेटर के अंदर त्रुटि फेंक दें । RxJS में सभी कॉलबैक ट्राइ-कैच ब्लॉकों के साथ लिपटे हुए हैं, इसलिए इसे पकड़ा जाएगा और फिर एक errorअधिसूचना के रूप में भेजा जाएगा ।

इसका मतलब है कि आप कुछ भी नहीं लौटाते हैं और बस त्रुटि फेंकते हैं:

map(res => { 
  if (res.bearerToken) {
    return this.saveJwt(res.bearerToken); 
  } else {
    throw new Error('Valid token not returned');
  }
})

throwError()(पूर्व Observable.throw()RxJS 5 में) है कि सिर्फ एक भेजता है एक मानने योग्य है errorअधिसूचना लेकिन map()परवाह नहीं करता कि तुम क्या वापस जाएँ। यहां तक ​​कि अगर आप map()इसमें से एक ऑब्जर्वेबल लौटाते हैं, तो इसे nextअधिसूचना के रूप में पारित किया जाएगा ।

आखिरी बात, आपको शायद .catchError()( catch()RxJS 5 में पूर्व ) का उपयोग करने की आवश्यकता नहीं है । यदि आपको कोई साइड इफेक्ट्स करने की आवश्यकता होती है जब एक त्रुटि होती है तो उदाहरण के लिए इसका उपयोग करना बेहतर होता है tap(null, err => console.log(err))(पूर्व do()में RxJS 5)।

जनवरी 2019: आरएक्सजेएस 6 के लिए अपडेट किया गया


1
धन्यवाद @ स्मार्टिन - हां आपका समाधान काम करता है। मुझे वास्तव में मेरे लॉगर विधि के अंदर एक समस्या थी जो @ GünterZöchbauer ने बताई। मैं returnइसे से त्रुटि वस्तु के लिए किया था और अब यह पूरी तरह से काम करता है :) धन्यवाद!
हसन

@ स्मार्टिन: क्या आप कृपया विकसित कर सकते हैं कि हम आपके लिए क्यों नहीं चाहते हैं।
बॉब

1
@ याकूब क्योंकि ओपी catch()केवल लॉग करने के लिए और त्रुटि को रीथ्रो करने के लिए उपयोग कर रहा था , जो कि अनावश्यक है यदि आप केवल एक साइड-इफ़ेक्ट (त्रुटि को लॉग करना) करना चाहते हैं और बस यूज़ करना आसान हैdo()
मार्टीन

1
क्या यह समान है return throwError(new Error('Valid token not returned'));?
सिमोन_विवर

@Simon_Weaver नहीं यह नहीं है। return throwError()रिटर्न ए Observable<never>, यह सिर्फ अवलोकनीय स्ट्रीम को तुरंत बाधित करता है, बिना सभी को लौटाए।
मोनिका

25

अगर आपको ऐसा throw new Error()लगता है कि आप इसके बिना उपयोग कर सकते हैं throwError(...), तो switchMapइसके बजाय आप इसका उपयोग कर सकते हैं map(अंतर switchMapएक नया अवलोकन योग्य रिटर्न देता है):

// this is the import needed for throwError()
import { throwError } from 'rxjs';


// RxJS 6+ syntax
this.httpPost.pipe(switchMap(res => { 
   if (res.bearerToken) {
      return of(this.saveJwt(res.bearerToken)); 
   } 
   else {
      return throwError('Valid token not returned');  // this is 
   }
});

या अधिक संक्षेप में:

this.httpPost.pipe(switchMap(res => (res.bearerToken) ? 
                                    of(this.saveJwt(res.bearerToken)) : 
                                    throwError('Valid token not returned')
));

व्यवहार समान होगा, यह सिर्फ अलग सिंटैक्स है।

आप वस्तुतः पाइप में http अवलोकनीय से 'स्विच' को एक अलग अवलोकनीय कह रहे हैं, जो या तो आउटपुट मान को 'रैपिंग' कर रहा है, या एक नया 'एरर' अवलोकनीय है।

डालने के लिए मत भूलना ofया आपको कुछ भ्रामक त्रुटि संदेश मिलेंगे।

इसके अलावा 'स्विचपॉइंट' की सुंदरता यह है कि आप कमांड की एक पूरी नई 'चेन' वापस कर सकते हैं यदि आप चाहते हैं - जो भी तर्क के साथ करने की आवश्यकता है saveJwt


4
एक बार जब मैंने switchMapएक अतुल्यकालिक ifबयान के बारे में सोचना शुरू कर दिया - चीजों ने बहुत अधिक समझ में आ गया :-)
साइमन_वेअर

3

भले ही यह प्रश्न पहले से ही उत्तर दिया गया है, मैं अपना दृष्टिकोण साझा करना चाहूंगा (भले ही यह ऊपर से थोड़ा अलग हो)।

मैं तय करूंगा कि मैपिंग से अलग क्या है और इसके विपरीत। मुझे यकीन नहीं है कि इसके लिए कौन सा ऑपरेटर सबसे अच्छा है इसलिए मैं इसका उपयोग करूंगा tap

this.httpPost.pipe(
  tap(res => { 
    if (!res.bearerToken) {
      throw new Error('Valid token not returned');
    }
  }),
  map(res => this.saveJwt(res.bearerToken)),
);

के वापसी मूल्य tapको नजरअंदाज कर दिया जाता है। यह कोड अलग-अलग काम करता है, जैसा कि वह कहता है
sf

मुझे अभी भी rxjs की आदत हो रही है। स्विचपाइप का उपयोग करना बेहतर होगा? क्या कोई अलग ऑपरेटर सुझा सकता है या सीधे संपादित कर सकता है?
क्रिस्चो8989

मुझे लगता है कि सुझाया throw new Error()गया अब तक का सबसे अच्छा विकल्प है
sf
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.