Angular中Map/Catch返回相同值却触发流类型错误的问题求助
Angular中catch分支返回普通对象导致的Stream错误分析
先来看你写的这段代码:
let currentTime:number = (new Date()).getTime(); return this.authenticationService.login(credential) .map(data => { const token = data.token; const id = data.id; sessionStorage.setItem('userData', JSON.stringify({currentTime, token, id})); return JSON.parse(sessionStorage.getItem('userData')); }) .catch(error => { sessionStorage.setItem('userData', JSON.stringify({currentTime, error})); return JSON.parse(sessionStorage.getItem('userData')); });
你提到map分支的return完全正常,但catch分支一执行就触发了这个错误:
core.js:1598 ERROR TypeError: You provided an invalid object where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.
错误原因
这其实是RxJS操作符的设计差异导致的:
- map是值转换操作符:它的作用是把流里的每个值转换成另一个值,你可以返回任意普通类型的数据(对象、字符串、数字等),RxJS会自动把这个值包装成一个新的Observable,继续往下传递给订阅者;
- catch是错误恢复操作符:它的职责是捕获流中的错误,然后返回一个合法的流对象——这个对象必须是Observable、Promise、数组或者可迭代对象中的一种。你现在直接返回了解析后的
userData普通对象,不符合catch的要求,所以RxJS就抛出了这个错误。
解决方案
只需要把catch里返回的对象包装成一个Observable就行,根据你用的RxJS版本不同,写法略有区别:
RxJS 5.x(对应Angular 5及更早版本)
// 先导入Observable import { Observable } from 'rxjs'; // ... .catch(error => { sessionStorage.setItem('userData', JSON.stringify({currentTime, error})); const userData = JSON.parse(sessionStorage.getItem('userData')); return Observable.of(userData); // 把普通对象包装成Observable });
RxJS 6+(Angular 6及以后版本,推荐pipe写法)
// 先导入需要的操作符 import { of } from 'rxjs'; import { map, catchError } from 'rxjs/operators'; // ... let currentTime:number = (new Date()).getTime(); return this.authenticationService.login(credential).pipe( map(data => { const token = data.token; const id = data.id; sessionStorage.setItem('userData', JSON.stringify({currentTime, token, id})); return JSON.parse(sessionStorage.getItem('userData')); }), catchError(error => { sessionStorage.setItem('userData', JSON.stringify({currentTime, error})); const userData = JSON.parse(sessionStorage.getItem('userData')); return of(userData); // 用of()包装成Observable }) );
这样修改后,catch分支就返回了一个合法的Observable流,订阅者就能正常接收值,不会再触发那个错误了。
内容的提问来源于stack exchange,提问作者olegario
相关产品推荐
相关产品推荐

