【问题标题】:Type 'void' is not assignable to type 'Observable<any>' How can I fix this?类型 'void' 不可分配给类型 'Observable<any>' 我该如何解决这个问题?
【发布时间】:2021-08-18 23:33:08
【问题描述】:

我正在尝试将我的 API 的返回值传递给我的 BehaviorSubject,但我遇到了上面的 Typescript 错误。我不清楚如何解决它。导致错误的代码行是 return this.sleepReponse.next(score) 这应该如何传递给我的 BehaviorSubject?

 export class SleepService {
    private endpoint = '';
    private sleepResponse = new BehaviorSubject<any>({});
    currentResponse = this.sleepResponse.asObservable();
  
    constructor(private http: HttpClient) { }

    public postSleepDuration(score: string, forceResponse?: boolean, errorCode?: number): Observable<any | HttpErrorResponse> {

        if (forceResponse === undefined) {
            return this.http.post<any>(this.endpoint, score );
        } else {
            const accounts = RESULTS_MOCK;
            const error = mockError(errorCode, this.endpoint);
            console.log('forceREsponse', of(accounts))

            let response = !!forceResponse ? of(accounts) : throwError(error);
            return this.sleepResponse.next(response)
        }
    }
}

const RESULTS_MOCK: any = {
    count: 1,
    next: null,
    previous: null,
    status: 200,
    results: [
        {
            id: "1",
            name: "Asleep and In bed results"
        }
    ]
}

【问题讨论】:

  • 删除退货。只需将数据作为 this.variable.next(data);

标签: angular observable behaviorsubject


【解决方案1】:

使用管道工作。

public postSleepDuration(score: string, forceResponse?: boolean, errorCode?: number): Observable<any | HttpErrorResponse> {

    if (forceResponse === undefined) {
        return this.http.post<any>(this.endpoint, score );
    } else {
        const accounts = RESULTS_MOCK;
        const mockedError = mockError(errorCode);

        return of(accounts).pipe(
            tap(response => {
                this.sleepResponse.next(response)
            }),
            catchError(error => 
                throwError(mockedError) )
        )
    }
}

【讨论】:

    【解决方案2】:

    关于 Angular 最好的事情之一是通过构造函数传递所有依赖项的模式,并将许多依赖项定义为抽象类而不是具体实现。

    因此,如果您想测试 SleepService,您可以将模拟逻辑从 SleepService 内部移至其依赖项,让 SleepService 非常简单:

    import { Observable } from 'rxjs';
    import { HttpClient, HttpErrorResponse } from '@angular/common/http';
    
    export class SleepService {
      private endpoint = '';
    
      constructor(private http: HttpClient) { }
    
      postSleepDuration(score: string): Observable<any | HttpErrorResponse> {
        return this.http.post<any>(this.endpoint, score);
      }
    }
    

    并提供具有模拟 HttpHandler 依赖项的 HttpClient 实例。这个HttpHandler 实现只需要一个方法handle(),它可以访问正在生成的HttpRequest,因此它可以根据测试做出适当的反应。

    它可以像硬编码的响应/错误一样简单,例如在成功的情况下,类似于:

    import { of, Observable } from 'rxjs';
    import { HttpClient, HttpEvent, HttpHandler, HttpRequest, HttpResponse } from '@angular/common/http';
    import { SleepService } from './sleep-service';
    
    const RESULTS_MOCK: any = {
      count: 1,
      next: null,
      previous: null,
      status: 200,
      results: [
        {
          id: '1',
          name: 'Asleep and In bed results'
        }
      ]
    }
    
    class OkHandler implements HttpHandler {
      handle(request: HttpRequest<any>): Observable<HttpEvent<any>> {
        return of(new HttpResponse({body: RESULTS_MOCK}));
      }
    }
    
    const okService = new SleepService(new HttpClient(new OkHandler()));
    okService.postSleepDuration('test').subscribe({
      next(x) { console.log(JSON.stringify(x, null, 2)); }
    });
    

    在失败的情况下,类似:

    import { throwError, Observable } from 'rxjs';
    import { HttpClient, HttpErrorResponse, HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http';
    import { SleepService } from './sleep-service';
    
    class ErrHandler implements HttpHandler {
      handle(request: HttpRequest<any>): Observable<HttpEvent<any>> {
        return throwError(new HttpErrorResponse({ error: mockedError }));
      }
    }
    
    const errService = new SleepService(new HttpClient(new ErrHandler()));
    errService.postSleepDuration('test').subscribe({
      error(x) { console.log(JSON.stringify(x, null, 2)); }
    });
    

    或者您可以提供单个 HttpHandler 实现,该实现根据其状态具有不同的行为,例如:

    import { of, throwError, Observable } from 'rxjs';
    import { HttpClient, HttpErrorResponse, HttpEvent, HttpHandler, HttpRequest, HttpResponse } from '@angular/common/http';
    import { SleepService } from './sleep-service';
    
    function mockError(errorCode: number, endpoint: string) {
      return `${errorCode}: ${endpoint}`;
    }
    
    const RESULTS_MOCK: any = {
      count: 1,
      next: null,
      previous: null,
      status: 200,
      results: [
        {
          id: '1',
          name: 'Asleep and In bed results'
        }
      ]
    }
    
    class Handler implements HttpHandler {
      errorCode?: number;
    
      handle(request: HttpRequest<any>): Observable<HttpEvent<any>> {
        if (this.errorCode !== undefined) {
          return throwError(new HttpErrorResponse({ error: mockError(this.errorCode, request.url) }));
        } else {
          return of(new HttpResponse({body: RESULTS_MOCK}));
        }
      }
    }
    
    const handler = new Handler();
    const service = new SleepService(new HttpClient(handler));
    
    service.postSleepDuration('test').subscribe({
      next(x) { console.log(JSON.stringify(x, null, 2)); }
    });
    
    handler.errorCode = 42;
    
    service.postSleepDuration('test').subscribe({
      error(x) { console.log(JSON.stringify(x, null, 2)); }
    });
    

    【讨论】:

      猜你喜欢
      • 2021-09-23
      • 2018-08-14
      • 2017-08-12
      • 2021-12-10
      • 2018-08-30
      • 2020-05-28
      • 1970-01-01
      • 2018-03-09
      • 2018-04-19
      相关资源
      最近更新 更多