RxJs Observable - 通过发出默认值来处理404

时间:2017-03-12 17:41:06

标签: angular typescript rxjs observable

我打电话给MS Graph获取用户的照片:

    // lets get the photo itself
    let photo$ = this.graph.get$(`users/${id}/photo/$value`, ResponseContentType.Blob)
        .map(resp => {
            return new Blob([resp.blob()], { type: resp.headers.get['Content-Type']}); })
        .map(photo => {
            let urlCreator = window.URL;
            return this.sanitizer
                .bypassSecurityTrustUrl(urlCreator.createObjectURL(photo));
        })
        .catch(function (e) {
            if(e.status === 404) {
                // no photo for this user!
                console.log(`No photo for user ${id}!  Returning default...`);
                return undefined;
            }
        })
        .toPromise();

然而,许多用户没有照片。在这种情况下,我想要做的是创建一个默认照片的对象URL(也许是these之一)并从Observable中发出。或者甚至只从Observable发出一个undefined,我可以通过显示一些默认图像在前端处理。

我知道我的捕获正在解雇,因为我在浏览器控制台中看到了这一点:

  

没有用户的照片xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx!返回   默认...(输出编辑)

我实际上为每个用户提取了许多不同的数据位,每个用户都在自己的Observable中。然后我将每个Observable转换为Promises,然后对所有这些进行Promise.all()

    // let's pull all of this together to form a ConcreteUser
    return Promise.all([photo$, ...])
        .then(values => {
            const photo = values[0];
            ...

问题出在用户照片404的情况下,整个Promise.all中止,我无法检索用户。

我尝试在photo$ observable中捕获错误并发出undefined(我计划稍后处理),但它似乎没有做我想要的。

如何在我的Observable中处理404s,并发出其他东西(可能是undefined)而不是杀死observable?

2 个答案:

答案 0 :(得分:6)

我想我可能已经弄明白了。浏览器控制台中隐藏着一个提示...

  

TypeError:您提供了“未定义”,其中包含预期的流。您   可以提供Observable,Promise,Array或Iterable。

阅读RxJs documentation on error handling表明他们正在做我想做的事情,所以我对此感到有些困惑。但后来我注意到在文档中他们称之为神秘函数getCachedVersion(),我假设它返回了一个真正的缓存函数。但是,如果他们返回了Observable.of()一些实际缓存的东西,那么这可以解释它。

当我将我的捕获代码更改为:

        .catch(function (e) {
            if(e.status === 404) {
                // no photo for this user!
                console.log(`No photo for user ${id}!  Returning default...`);
                return Observable.of(undefined);
            }
        })

......一切都开始了。

答案 1 :(得分:0)

现在将Johns answer转换为最新的rxjs实现,如下所示:

import { Observable, throwError, of } from 'rxjs';
import { catchError } from 'rxjs/operators';

const observale: Observable<>; 

observale.pipe(
   catchError(err => {
       if(err.error.status === 404) {
          return of(undefined);
       } else {
          //important to use the rxjs error here not the standard one
          return throwError(err);
       }
   })
)
.subscribe(val => {
      console.log('success but may be undefined');
   }, err => {
      console.log('error');
});