Search code examples
angulartypescriptangular-httpclient

angular 16 async await for http post finish


I have a function called login() that calls an HTTP POST request to generate a SID. When the function ends I do apply to a local variable named this.sid. When I call the Login() function I expect the variable thid.sid to contain the SID value but instead I get undefined

  sid: string | undefined;

  login() {
    const body = `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://www.ca.com/UnicenterServicePlus/ServiceDesk">
              <soapenv:Header/>
              <soapenv:Body>
                  <ser:login>
                    <username>servicedesk</username>
                    <password>?</password>
                  </ser:login>
              </soapenv:Body>
            </soapenv:Envelope>`

    this.http
      .post(this.soapURL, body, {
        headers: {
          'SOAPAction': '""',
          'Content-Type': 'text/xml;charset=UTF-8'
        },
        responseType: 'text'
      })
      .subscribe({
        next: (res) => {
          const parser = new xml2js.Parser({ strict: false, trim: true });
          parser.parseString(res, (err, result) => {
            this.soapenvEnvelope = result;
            this.sid = this.soapenvEnvelope?.["SOAPENV:ENVELOPE"]["SOAPENV:BODY"][0].LOGINRESPONSE[0].LOGINRETURN[0]._;
          });
          console.log(this.sid )
        },
        error: (ex) => {
          console.log(ex)
        }
      })
  }


  foo() {
    this.login()
    console.log(this.sid) // undefined
  }

Solution

  • The code inside the subscribe is asynchronous ( waits for the API to complete). The code after the login call is synchronous ( Does not wait for the API to complete), so you are getting this issue. To solve this, you can just move your code inside the subscribe, so that the code happens sequentially.

    To learn more I recommend this What is event loop, which helped me out to learn.

    .subscribe({
        next: (res) => {
          const parser = new xml2js.Parser({ strict: false, trim: true });
          parser.parseString(res, (err, result) => {
            this.soapenvEnvelope = result;
            this.sid = this.soapenvEnvelope?.["SOAPENV:ENVELOPE"]["SOAPENV:BODY"][0].LOGINRESPONSE[0].LOGINRETURN[0]._;
          });
          console.log(this.sid )
          // move your code here and execute inside the subscribe.
        },
        error: (ex) => {
          console.log(ex)
        }
      })