Testing an asynchronous function in JavaScript can lead to the error message: "Have you neglected to utilize await?"

Here is an example of the code I am working with:

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 main issue I am encountering is due to JavaScript's asynchronous behavior, where the console.log('ITS COMPLICATED') statement gets executed before the one inside the callback function. My goal is to ensure that the first console.log runs before the last one!

To address this, I implemented Async/Await as shown below:

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

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

Therefore, I modified my getResponseFromURL() method to make use of async/await like so:

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();
   }
}

However, a challenge arose when testing the async function and checking for the status property of the container class. Prior to

expect.getResponseFromURL().getStatus().toBe(200)
, I encountered issues.

The test scenario is outlined below:

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

Presently, I am receiving an error related to .getStatus(), and I'm unsure how to overcome this particular hurdle.

"does not exist on Promise"

Answer №1

When looking at the code snippet provided, we see that await is being called on the outcome of invoking getStatus from the result obtained by calling

ContainerGlobals.getResponseFromURL()
.

The function

ContainerGlobals.getResponseFromURL()
returns a Promise, and direct invocation of getStatus() on this Promise triggers an error message stating that getStatus "does not exist on Promise".

To resolve this issue, it is necessary to apply await to the Promise generated by

ContainerGlobals.getResponseFromURL()
, followed by calling getStatus on the returned outcome of the await.

A quick fix for correcting this problem involves enclosing the await in parentheses:

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

Alternatively, for improved readability, you can split the line containing await into two separate lines:

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

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Prohibit communication by any means

Let's take a look at the following function overloads: function f(key: undefined); function f(key: string | undefined, value: object | undefined); I want to allow calls with a single explicit undefined argument f(undefined), but require two argument ...

Hide the FormArray in a Reactive Form if it is not populated or cannot be determined

As a newcomer to Angular 4, I've embarked on my first project and started learning the ropes. I have devised a Reactive Form to showcase a form structure that looks like this: Form (FormGroup) | --> aggLevels (FormArray) | --> ...

Utilizing Angular 2's Routerlink with *ngIf and Parameters

Currently, I am facing an issue with a routerlink that includes a parameter: http://localhost:4200/item/1 I am trying to figure out how to implement an *ngIf statement with a parameter.... Here is what I have attempted so far: <div *ngIf="router.url ...

Nextjs 14 experiences full page loading due to the presence of multiple root layouts

The issue I'm facing involves a full page load when navigating between two root layout pages In my Next.js application (NextJS 14), I have created two root layouts. However, when moving from the first layout to the second layout, it triggers a comple ...

Node: Await the completion of loading multiple images asynchronously

Despite seeing similar questions in the past, I'm struggling to solve my specific issue. My problem involves loading a batch of images before running another section of code. (async () => { const urls = <array of urls> await urls.map(url ...

Tips for creating an onClick event for a React Component that is passed as a prop to another component

I am currently in the process of creating a custom trigger component that can be passed down to another component. My goal is to implement a click event on this trigger component from the receiving component. If you'd like to see a live example, chec ...

Updating the data type of the Request object following the execution of the checkAuth middleware in Types

I'm relatively new to TypeScript and recently encountered an issue with extending the Request type. Although I managed to find a workaround, it doesn't sit well with me and I believe there may be a more optimal solution out there. Let's del ...

Condition not applying in the Modal

I implemented *ngif on a button to show/hide it based on a condition, but it's not working as expected. The button should appear when an item is selected from ng-select. Here is the button code: <button *ngIf="switch" (click)="productSaveInCart() ...

Arranging a collection of objects in alphabetical order

My current challenge involves sorting an array of objects alphabetically, and to simplify things, I have provided the example below. In my TypeScript code, I utilize splice to add and remove items from the object array. Array cars = [{ id: 1, ...

Guide on automatically inserting a colon (:) after every pair of characters in Angular

I am looking to automatically insert a colon (:) after every 2 characters in my input field: HTML <input nz-input type="text" appLimitInput="textAndNumbers" name="mac" formControlName="mac" (keydown.space)=&qu ...

What is the reason that TypeScript does not automatically infer void & {} as the never type?

When TypeScript's void type is used in combination with other types through intersection, the outcomes vary. type A = void & {} // A becomes void & {} type B = void & '1' // B becomes never type C = void & 1 // C becomes never type D = void ...

Creating a service in AngularJS 1.8 with ES6 modules that acts as a bridge to a class based API interface

As I continue to enhance a codebase that originally consisted of a mix of different versions of AngularJs and some unstructured code utilizing various versions of a software API, I encounter an interesting quirk. It appears that this API is accessible thro ...

Chrome Not Responding to Angular5 Debugging

I'm facing an issue where I used to be able to set breakpoints in my Angular code using developer tools, and it would pause correctly. However, recently the network files are not being mapped to my local files properly. For a detailed explanation, ple ...

Angular version 5 and above introduces a new feature called "openFromComponent" within the Snackbar component, facilitating seamless communication

Angular (v5.2.10) Snackbar --| Introduction |-- I am facing a scenario where an Angular component named "Parent" is initializing an Angular Material Snackbar known as snackBar. The snackbar is being passed in the component called SnackbarMessage, which ...

Incompatibility issues between NestJS and socket.io package

After diligently following the documentation, I attempted to install and work with socket.io on nestjs. However, I encountered multiple issues when installing packages. Despite trying different methods to update the package, nothing seemed to resolve the i ...

The 'RouterLink' JSX element type is missing any construct or call signatures

While researching this issue on the internet and Stack Overflow, I've noticed a common theme with problems related to React. An example can be found here. However, I am working with Vue and encountering errors in Vue's own components within a new ...

Developing client-side components with NextJS

I want to develop a single-page landing page where users can upload videos and there's a file size limit check before the upload. In my src/app/page.tsx file, I have the following code: import React from 'react'; import FileUpload from &apo ...

Best practice for incorporating types into a Redux-toolkit reducer

As someone who is relatively new to TypeScript, I have a specific goal in mind. I am looking to create an interface where: interface ActionType { fieldName: {any one key from the interface FormStateType listed below such as 'name', 'age&ap ...

Unraveling the Mystery of @Input and @Output Aliases in Angular 2

After researching about the @Input() and @Output() decorators, I discovered that we have the option to use an alias instead of the property name for these decorators. For example: class ProductImage { //Aliased @Input('myProduct') pro ...

The variable is currently undefined because it has an array assigned to it

Upon selecting multiple checkboxes for variants, I am retrieving checked data using the following method: get selectedIdsFromViolCategoriesFormArray(): string[] { return this.violCategories .filter((cat, catIdx) => this.violCategoriesFormArr. ...