【问题标题】:Returning an array of strings from httpClient using Observables使用 Observables 从 httpClient 返回一个字符串数组
【发布时间】:2019-06-28 21:10:54
【问题描述】:

我有一个返回字符串数组 (json) 的 API 端点,我正在尝试创建一个通过 Angular 服务吐出内容的页面。到目前为止,这是我所拥有的(我在 Angular 7 上):

export class FieldService {
  constructor(private httpClient: HttpClient) { }

  fieldTypesURL = 'http://localhost:3000/fields/types';

  public getTypes(): Observable<any[]> {
    return this.httpClient.get<any[]>(this.fieldTypesURL)
    .pipe(map((response: any) => response.json()),
      catchError((error: any) => Observable.throw(error.json().error || 'Server error')));
  }
}

我得到的编译错误如下:

Type 'Observable<any[]>' is missing the following properties from type 'Promise<string[]>': then, catch, [Symbol.toStringTag], finally

为什么在我尝试使用 Observable 时在这里提到 Promise?欢迎任何想法!

【问题讨论】:

  • 我认为在这种情况下你可以跳过pipe,代码看起来不错
  • 使用 httpClient 不需要 response.json()
  • 你使用的是什么版本的 TypeScript? (在你的 package.json 文件中定义)
  • 我正在使用 Typescript 版本:~3.2.2
  • 您显然正在尝试将 getTypes() 返回值分配给您定义为 Promise

标签: angular typescript


【解决方案1】:

当您使用 httpClient 时,它会自动将响应解析为 JSON。所以,.pipe(map((response: any) =&gt; response.json()) 可能是这里的错误。

另外,输入 'any' 更改为 'string'

试一试:

public getTypes(): Observable<string[]> {
return this.httpClient.get<string[]>(this.fieldTypesURL)
  .catch((error: any) => Observable.throw(( error && JSON.parse(error).error) || 'Server error')));
}

.json() 函数的作用几乎*与这里可以看到的相同 Angular Response.json() not documented

【讨论】:

  • 我通过删除该行来简化代码并最终得到一个更好的版本,但我仍然遇到完全相同的错误。我已经尝试了这篇文章中推荐的大量变体,但也没有运气:stackoverflow.com/questions/37208801/…
  • 很抱歉。见上文。
  • public getTypes(): Observable { return this.httpClient.get(this.fieldTypesURL); } ...是我当前的代码,它抛出了同样的错误。
【解决方案2】:

@hamzakhan 说得对,我们不需要将响应解析为 json。但是由于您的代码仍然无法正常工作,因此我刚刚将 Observable 更改为 Observable 以返回函数 getTypes() 的类型。 希望它好运..!!!!!!

export class FieldService {
  constructor(private httpClient: HttpClient) { }

  fieldTypesURL = 'http://localhost:3000/fields/types';

  public getTypes(): Observable<any> {
    return this.httpClient.get(this.fieldTypesURL)
    .pipe(map((response: any) => console.log(response),
      catchError((error: any) => Observable.throw(( error && JSON.parse(error).error) || 'Server error')));
  }
}

【讨论】:

    【解决方案3】:

    1) 使用泛型参数调用 httpClient 会为您进行 json 转换和类型转换。

    2) Observable#throw 已被弃用,请改用 throwError 运算符。另外,请确保您正确解析和处理错误。为你的错误指定一个类型肯定会增加类型安全性。

    3) 确保正确调用服务方法...

    // field.service.ts
    export class FieldService {
    
      constructor(private httpClient: HttpClient) { }
    
      fieldTypesURL = 'http://localhost:3000/fields/types';
    
      public getTypes(): Observable<string[]> {
        return this.httpClient.get<string[]>(this.fieldTypesURL).pipe(
          catchError((r: HttpErrorResponse) => throwError(r.error || 'Server error'))
        );
      }
    }
    
    // your.component.ts
    export class YourComponent {
    
      constructor(private fieldService: FieldService){}
    
      // ... component logic ...
    
      public types: string[];
      public types$: Observable<string[]>;
    
      public callService() {
    
        // A correct call
        this.fieldService.getTypes().subscribe(types => this.types = types)
    
        // Also a correct call with a bit of observable stream processing
        this.types$ = this.fieldService.getTypes().pipe(
          catchError((err: any) => {
            // Component-side error processing can be put here
            return throwError(err);
          }),
          flatMap(types => types),
          filter(type => !!type),
          map(type => type.trim()),
          toArray()
        );
    
        // Incorrect calls (compiler errors)
        this.fieldService.getTypes().then(types => /* whatever */);
        this.fieldService.getTypes().catch(err => /* whatever */);
        let r: Promise<string[]> = this.fieldService.getTypes();
      }
    }
    

    希望这会有所帮助:-)

    【讨论】:

      【解决方案4】:

      使用以下代码,因为 catchError(this.handleError) 将处理您的错误以及失败的 Http 请求。

      export class FieldService {
        constructor(private httpClient: HttpClient) { }
      
        fieldTypesURL = 'http://localhost:3000/fields/types';
      
        public getTypes(): Observable<any[]> {
          return this.httpClient.get<any[]>(this.fieldTypesURL)
          .pipe(
            catchError(this.handleError)
          );
        }
      
        private handleError(error: HttpErrorResponse) {
      
          if (error.error instanceof ErrorEvent) {
            // A client-side or network error occurred. Handle it accordingly.
            console.log('An error occurred:', error.error.message);
          } else {
            // The backend returned an unsuccessful response code.
            // The response body may contain clues as to what went wrong,
            console.log(
              `Backend returned code ${error.statusText}, ` +
              `body was: `,error.message);
          }
          // return an observable with a user-facing error message
          return _throw('Something went wrong. Please try again later.');
        };
      }
      

      如果您注意到,我从代码中删除了 .map() 只是因为它用于对 响应数据 执行某些操作,这不是必需的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-04
        • 2012-08-21
        • 1970-01-01
        • 2013-04-14
        • 2017-10-09
        • 1970-01-01
        相关资源
        最近更新 更多