6
votes

My code looks like this:

public getUrl(url) {
//returns URL
 ... }

public getResponseFromURL(): container {
  let myStatus = 4;
  const abc = http.get(url, (respon) => 
  const { statusCode } = respon;
  myStatus = statusCode;
  console.log('Inside callback' +myStatus);
  .on('error', (err) => {
  console.log('Things have gone wrong' + err);
  });
  console.log('ITS COMPLICATED' +myStatus);
  return new Container(status, body, header);
  }
}

The problem I am facing is because of the asynchronous nature of JS and the console.log('ITS COMPLICATED') gets executed before the one in the callback function. I am trying to have the first one executed before the last console.log!

I am using Async/Await like below:

  public timeoutPromise(time: any) {
    return new Promise((resolve) => {
      setTimeout(() => {
        resolve(Date.now());
      }, time);
    });
  }

  public doSomethingAsync() {
    return this.timeoutPromise(1000);
  }

As a result changed my getResponseFromURL() to:

public async getResponseFromURL(): Promise<container> {
    this.myStatus = 7;
    console.log(0);
    await this.doSomethingAsync();
    console.log(1);
    const abc = http.get(url, (respon) => {
      const { statusCode } = respon;
      this.myStatus = statusCode;
      console.log('Inside Callback ' + statusCode);
    }).on('error', (err) => {
      console.log('Things have gone wrong ' + err);
    });
    await this.doSomethingAsync();
    console.log(2);
    await this.doSomethingAsync();
    console.log('Is it simple lalala ' + this.myStatus);
    await this.doSomethingAsync();
   }
}

The problem with doing this was if my container class (return type of getResponseFromURL()) is a container for status and body when I am testing this async function, before expect.getResponseFromURL().getStatus().toBe(200) would work.

Test looks like below:

  test('Async function', async () => {
    expect.assertions(1);
    const data = await ContainerGlobals.getResponseFromURL().getStatus();
    expect(data).toBe(207);
  });

Now I am getting error from .getStatus() and I am not sure how to bypass this error?

"does not exist on Promise"

1
You could try something like this async doSomethingAsync() { this.asyncResult = await this.httpClient.get(this.url).toPromise(); console.log('No issues, I will wait until promise is resolved..'); }Anoop Mc
@AnoopMc I am not sure I understand - what is this.httpClient and toPromise() here ?lanzchilz

1 Answers

4
votes

In the code above await is called on the result of calling getStatus on the result of calling ContainerGlobals.getResponseFromURL().

ContainerGlobals.getResponseFromURL() returns a Promise and immediately calling getStatus() on the Promise gives an error since getStatus "does not exist on Promise".

await needs to be called on the Promise returned by ContainerGlobals.getResponseFromURL(), and getStatus should be called on the result returned by await.

The quickest way to fix this is to throw parenthesis around the await:

test('Async function', async () => {
  expect.assertions(1);
  const data = (await ContainerGlobals.getResponseFromURL()).getStatus();
  expect(data).toBe(207);  // SUCCESS
});

...but you might want to split the await line into two lines for readability:

test('Async function', async () => {
  expect.assertions(1);
  const result = await ContainerGlobals.getResponseFromURL();  // let the Promise resolve
  const data = result.getStatus();  // call getStatus on the result
  expect(data).toBe(207);  // SUCCESS
});