Search code examples
angularrxjs6

TypeScript code getting executed but it shouldn't


I am using TypeScript and Rxjs. I am sending data to the server using Rxjs. I have also implemented a custom interceptor. The interceptor returns a type:0 event and also the response from the server as two separate events. I suppose type:0 means that the request has been sent.

I don't want to do anything when type:0 event is received so I have put checks in the code to ignore it but my code still executes a piece of logic even if the event is type:0. Have I made a mistake?

The code where I send the request is

let response:ServerResponseAPI = this.dataManagementService.addData(this.newData);
      console.log("add practice question - response is ",response); //I see this print
      if (response != null) { //for type:0, this should be null but isn't

        let isResponseStructureOK: boolean = this.helper.validateServerResponseStructure(response);
        if (isResponseStructureOK) {
          console.log("received response from server: " + response.result);
          let dialogComponentRef: ComponentRef<DialogBoxComponent> = this.maxFilesDialogContainerRef.createComponent(this.dialogFactory);
          dialogComponentRef.instance.dialogMessage = response.result + ": " + response['additional-info'];
          dialogComponentRef.instance.dialogID = "maxFilesDialog";
          dialogComponentRef.instance.dialogShow();
          return;
        } else {  //response structure not ok
          console.log("received incorrect response structure from server: ", response);
          let dialogComponentRef: ComponentRef<DialogBoxComponent> = this.maxFilesDialogContainerRef.createComponent(this.dialogFactory);
          dialogComponentRef.instance.dialogMessage = "Server error";
          dialogComponentRef.instance.dialogID = "maxFilesDialog";
          dialogComponentRef.instance.dialogShow();
          return;
        }
      } //end of not null response

addData is

addData(data:Data):ServerResponseAPI{
    console.log("In DataManagementService: addData: ",data);

    return this.bs.createData(data).subscribe((resBody/*:any*/)=>{
      if(resBody != null) { //null means that the response wasn't an HttpResponse but probably some internal Rxjs event (eg type 0)
        console.log('response from server:', resBody);
        <ServerResponseAPI>resBody; //returning response body which is of type ServerResponseAPI;
      }
      else null; //this means type0 event
    });
  }

and bs.createData is

public createData(data:Data):any{
    console.log('contacting server at '+this.API_URL +this.NEW_DATA_URL +" with data "+data+ " with httpOptions "+httpOptions.withCredentials + ","+httpOptions.headers );

    let newData = new DataAPI(data)

    let body = JSON.stringify(newData); 

    return this.http.post(this.NEW_DATA_URL,body,httpOptions)
      .map(response => { //I suppose this could be any event from custom interceptor 
        if(response instanceof HttpResponse)
        {
          console.log('response from backend service:', response);

          let result = <HttpResponse<any>>response;

          return result.body; //return body of response which ideally should be of type ServerResponseAPI
        }
        else {
          console.log("not an http response")

          return null; //returning null for non-HttpResponse type
        }
      })
      .catch(this.handleError); //error handler if Observable fails

  }

The interceptor is

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {


    console.log("outgoing request",request);
    const idToken = localStorage.getItem("id_token"); //JWT authentication stuff
    console.log("id token is "+idToken);

    if (idToken) {
      const cloned = request.clone({
        headers: request.headers.set("X-Auth-Token",
          idToken)
      });
      console.log("new outgoing request", request);
      return next.handle(cloned) 
      .do((ev: any) => { 
        console.log("got an event",ev)
      })
      .catch(errorResponse => {
          console.log("caught error from server",errorResponse)
          return observableThrowError(errorResponse);
      });
    }
    else {
      return next
      .handle(request) 
      .do((ev: any) => { 
          console.log("got an event",ev)
            })
      .catch(errorResponse => {
          console.log("caught error from server",errorResponse)
          return observableThrowError(errorResponse);
      });
    }

      }

When I run the code, I see this message which I shouldn't

got an event {type: 0} new-data.component.ts:255 add data- response is Subscriber {closed: false, _parent: null, _parents: null, _subscriptions: Array(1), syncErrorValue: null, …} new-practice-question.component.ts:270 received incorrect response structure from server: Subscriber {closed: false, _parent: null, _parents: null, _subscriptions: Array(1), syncErrorValue: null, …}

I suppose I get HttpEvent from Rxjs which is a union of HttpResponse.

type HttpEvent<T> = HttpSentEvent | HttpHeaderResponse | HttpResponse<T> | HttpProgressEvent | HttpUserEvent<T>;

How could I check that HttpEvent is of type HttpResponse?


Solution

  • Take a look at this piece of code you have:

    addData(data:Data):ServerResponseAPI{
        console.log("In DataManagementService: addData: ",data);
    
        return this.bs.createData(data).subscribe((resBody/*:any*/)=>{ (...)
    

    Now look at this one a few lines before:

    let response:ServerResponseAPI = this.dataManagementService.addData(this.newData);
    

    There are few things not correct there:

    1- addData does not return an object of type/interface ServerResponseAPI, it returns a subscription object from your subscription action, so that you can do subscription.unsubscribe() later on if needed.

    2- What you have in your response variable is not a response, you are treating that piece of code as if it were synchronous, it is not.