Saya ingin melempar kesalahan dari operator peta yang dapat saya amati berdasarkan suatu kondisi. Misalnya jika data API yang benar tidak diterima. Silakan lihat kode berikut:
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.") );
}
Pada dasarnya seperti yang Anda lihat di kode, jika respons (objek res) tidak memiliki 'bearerToken', saya ingin mengeluarkan kesalahan. Sehingga dalam langganan saya ini masuk ke parameter ke-2 (handleError) yang disebutkan di bawah ini.
.subscribe(success, handleError)
Ada saran?
angular
typescript
rxjs
Hassan
sumber
sumber
throw 'Valid token not returned';
?return throw 'message here'
tetapi berfungsi tanpareturn
kata kunci. Biarkan saya memeriksa apakah itu berfungsi dengan benar secara logis.subscribe
metode dan.finally()
dalam aliran juga terpicu. (Namun eksekusi dihentikan yang merupakan hal yang baik)Jawaban:
Buang saja kesalahan di dalam
map()
operator. Semua callback di RxJS dibungkus dengan blok coba-tangkap sehingga akan ditangkap dan kemudian dikirim sebagaierror
notifikasi.Ini berarti Anda tidak mengembalikan apa pun dan hanya membuang kesalahan:
map(res => { if (res.bearerToken) { return this.saveJwt(res.bearerToken); } else { throw new Error('Valid token not returned'); } })
The
throwError()
(mantanObservable.throw()
di RxJS 5) adalah Observable yang hanya mengirimerror
pemberitahuan tetapimap()
tidak peduli apa yang Anda kembalikan. Meskipun Anda mengembalikan Observablemap()
darinya akan diteruskan sebagainext
notifikasi.Hal terakhir, Anda mungkin tidak perlu menggunakan
.catchError()
(sebelumnyacatch()
di RxJS 5). Jika Anda perlu melakukan efek samping ketika terjadi kesalahan, lebih baik menggunakantap(null, err => console.log(err))
(sebelumnyado()
di RxJS 5) misalnya.Jan 2019: Diperbarui untuk RxJS 6
sumber
return
objek kesalahan darinya dan sekarang berfungsi dengan sempurna :) Terima kasih!catch()
hanya menggunakan untuk mencatat dan mengembalikan kesalahan, yang tidak perlu jika Anda hanya ingin melakukan efek samping (mencatat kesalahan) dan lebih mudah menggunakannyado()
return throwError(new Error('Valid token not returned'));
?return throwError()
mengembalikan sebuahObservable<never>
, ini hanya mengganggu aliran yang dapat diamati dengan segera, tanpa kembali sama sekali.Jika Anda merasa seperti
throw new Error()
tidak dapat diamati-seperti Anda dapat menggunakanthrowError(...)
denganswitchMap
alih - alihmap
(perbedaannyaswitchMap
mengembalikan yang dapat diamati baru):// 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 } });
atau lebih tepatnya:
this.httpPost.pipe(switchMap(res => (res.bearerToken) ? of(this.saveJwt(res.bearerToken)) : throwError('Valid token not returned') ));
Perilakunya akan sama, hanya sintaks yang berbeda.
Anda benar-benar mengatakan 'beralih' dari http yang dapat diamati di pipa ke yang dapat diamati yang berbeda, yang hanya 'membungkus' nilai output, atau 'kesalahan' baru yang dapat diamati.
Jangan lupa untuk meletakkan
of
atau Anda akan mendapatkan beberapa pesan kesalahan yang membingungkan.Juga keindahan 'switchMap' adalah Anda dapat mengembalikan 'rantai' perintah yang sama sekali baru jika Anda mau - untuk logika apa pun yang perlu dilakukan
saveJwt
.sumber
switchMap
sebagaiif
pernyataan asinkron - semuanya menjadi lebih masuk akal :-)Meskipun pertanyaan ini sudah terjawab, saya ingin berbagi pendekatan saya sendiri (walaupun hanya sedikit berbeda dari yang di atas).
Saya akan memutuskan apa yang dikembalikan terpisah dari pemetaan dan sebaliknya. Saya tidak yakin operator mana yang terbaik untuk ini jadi saya akan gunakan
tap
.this.httpPost.pipe( tap(res => { if (!res.bearerToken) { throw new Error('Valid token not returned'); } }), map(res => this.saveJwt(res.bearerToken)), );
sumber
tap
diabaikan. kode ini melakukan hal yang berbeda dari yang dikatakanthrow new Error()
adalah opsi terbaik sejauh ini