简体   繁体   English

在 observable 中调用返回另一个 observable 的方法时出错

[英]Getting error when calling a method inside observable which returns another observable

I am new to angular and observable.我是 angular 和 observable 的新手。 I have tried flatMap, swithMap and concatMap, but nothing helps.我尝试过 flatMap、swithMap 和 concatMap,但没有任何帮助。 I have got the error " You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable ."我收到错误消息“您在需要流的地方提供了 'undefined'。您可以提供 Observable、Promise、Array 或 Iterable 。” When the code of switch case 1 runs of inputprocessing method,while the default case works completely fine.当 switch case 1 的代码运行 inputprocessing 方法时,而 default case 完全正常。

app.component.ts app.component.ts

 export class AppComponent implements OnInit, AfterViewChecked, OnChanges {
  ProcessInput(input: string, session: string): void {
    this.appService
      .ProcessInput(input, session)//this works fine and returns the response.
      .pipe(
        concatMap((res: any) => {
          return this.inputProcessing.inputProcessing(res);
        })
      )
      .subscribe(
        res => {
          this.arr.push("TEST");
        },
        err => {
          console.log(err);
        }
      );
  }
  }

inputprocessing.service.ts inputprocessing.service.ts

import "reflect-metadata";
import { Injectable } from "@angular/core";
import { Container, inject, injectable, AsyncContainerModule } from "inversify";
import { OutputResponse } from "../response";
import { PrescriptionStatus } from "src/Classes/PrescriptionStatus";
import { service } from "./service.service";
import { HttpClient } from "@angular/common/http";
import { CourierMode } from "../enums/CourierMode";
import { Observable, of } from "rxjs";
import { switchMap, flatMap, concatMap } from "rxjs/operators";
import { PrescriptionStatusMain } from "src/models/PrescriptionStatusResponse";

@Injectable({
  providedIn: "root"
})
export class InputprocessingService {
  constructor(private service: service,private http: HttpClient) {}

  responseText: string;
  returnMessage: string;
  inputProcessing(response: OutputResponse): Observable<any> {

    this.responseText = response.output.generic[0].text;
    //works completely fine with default case, but when case 1: runs it gave an error
    switch (this.responseText) {
      case "1": {

        const obsFail = new Observable(observer => {
          observer.next(this.returnMessage);
          observer.error();
          observer.complete();
        });

        this.service.getStatus().pipe(
          concatMap((res: StatusMain) => {
            return obsFail ;
          })
        );
        break;
      }

      default: {
        const obs = new Observable(observer => {
          observer.next(this.responseText);
          observer.complete();
        });
        return obs;
      }
    }
  }
}

service.ts服务.ts

import * as request from "request";
import * as request_promise from "request-promise-native";
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { StatusMain } from "src/models/StatusResponse";
import { Observable } from "rxjs";
@Injectable()
export class service {
  constructor(private http: HttpClient) {}

  getStatus(): Observable<StatusMain> {
    const body = { bdate: "1999/05/01" };
    return this.http.post<StatusMain>(
      "http://localhost:49995/api/Status",
      body
    );
  }
}

inputProcessing function in your service needs to return an observable.您服务中的inputProcessing函数需要返回一个 observable。 With your implementation the created observable only emits the value, while the concatMap expects an observable.在您的实现中,创建的 observable 只发出值,而concatMap需要一个 observable。 Hence the error: You provided 'undefined' where a stream was expected.因此出现错误:您在需要流的地方提供了“未定义”。 You can provide an Observable, Promise, Array, or Iterable.您可以提供 Observable、Promise、Array 或 Iterable。

Try this:尝试这个:

 export class AppComponent implements OnInit, AfterViewChecked, OnChanges {
  ProcessInput(input: string, session: string): void {
    this.appService
      .ProcessInput(input, session)//this works fine and returns the response.
      .pipe(
        flatMap((res: any) => {
          return this.inputProcessing.inputProcessing(res);
        })
      )
      .subscribe(
        res => {
          this.arr.push("TEST");
        },
        err => {
          console.log(err);
        }
      );
   }
  }

And in your service:在您的服务中:

@Injectable({
  providedIn: "root"
})
export class InputprocessingService {
  constructor(private service: service,private http: HttpClient) {}

  responseText: string;
  returnMessage: string;
  inputProcessing(response: OutputResponse): Observable<any> {

    this.responseText = response.output.generic[0].text;
    let returnObservable;

    //works completely fine with default case, but when case 1: runs it gave an error
    switch (this.responseText) {
      case "1": {

        const obsFail = new Observable(observer => {
          observer.next(this.returnMessage);
          observer.error();
          observer.complete();
        });

        returnObservable = this.service.getStatus().pipe(
          concatMap((res: StatusMain) => {
            return obsFail ;
          })
        );
        break;
      }

      default: {
        returnObservable = new Observable(observer => {
          observer.next(this.responseText);
          observer.complete();
        });
      }
    }

    return returnObservable;
  }
}

Note how AppComponent implements flatMap .注意AppComponent如何实现flatMap flatmap must return an observable. flatmap必须返回一个 observable。 Hence inputProcessing creates a local variable ( returnObservable ) which holds a reference to different observables (switch statement: case1, case2... default).因此inputProcessing创建了一个局部变量( returnObservable ),它保存对不同 observable 的引用(switch 语句:case1, case2... default)。

When the inner observables emit value, then returnObservable emits that value to the outer flatMap .当内部 observable 发出值时, returnObservable将该值发送到外部flatMap

inputprocessing.service.ts This code resolved the issue. inputprocessing.service.ts这段代码解决了这个问题。

@Injectable({
      providedIn: "root"
    })
    export class InputprocessingService {
      constructor(private service: service,private http: HttpClient) {}

      responseText: string;
      returnMessage: string;
      inputProcessing(response: OutputResponse): Observable<any> {

        this.responseText = response.output.generic[0].text;
        let returnObservable;

        //works completely fine with default case, but when case 1: runs it gave an error
        switch (this.responseText) {
          case "1": {      
    //This line solved the error.
            return this.service.getStatus().pipe(map(res=>{return res}));
            break;
          }

          default: {
            returnObservable = new Observable(observer => {
              observer.next(this.responseText);
              observer.complete();
            });
          }
        }

        return returnObservable;
      }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM