How can I ensure my function waits for a promise to be resolved using Async / Await?

I'm running into an issue where I want my function to keep executing until the nextPageToken is null. The problem occurs when the function runs for the first time, it waits for the promise to resolve. However, if there is a nextPageToken present in the response, the function doesn't wait for the response and triggers a stack overflow.

It seems like f() doesn't stop when await p.then() is invoked.

Do I have a misunderstanding of how async/await operates?

Any assistance would be greatly appreciated...

public apiResult2(path: string, objectName: string, params: any = { }) {
    let returnArray = [];
    const p = new Promise<any> ((resolve, reject) => {
      gapi.load('auth2:client', () => {
        gapi.client.request({
          path: path,
          params: params
        }).then(response => {
          // resolve this promise with the first key in the response object.
          resolve(response.result);
        }, reason => {
          console.log(reason);
          reject(reason.result);
        });
      });
    });
    let f = async () => {
      let nextPageToken = null;
      do {
        let r = await p.then(result => {
          if (result.hasOwnProperty(objectName)) {
            for (let obj of result[objectName]) {
              returnArray.push(obj);
            }
          }
          if (result.hasOwnProperty('nextPageToken')) {
            params.nextPageToken = result.nextPageToken;
            return result.nextPageToken;
            // nextPageToken = result.nextPageToken;
          } else {
            params.nextPageToken = null;
            return null;
            // nextPageToken = null;
          }
        });
        nextPageToken = r;
        console.log(r);
      } while (nextPageToken);
    };
    f();
    return returnArray;
  }

Answer №1

When your function requires an asynchronous call to be "awaited", it must also be marked as async. In the case of the apiResult2 function, it does not wait for the completion of the f call before returning returnArray.

UPDATE:

The key issue lies in attempting to reuse the promise p for multiple requests, which is not supported. The promise p will only contain the parameters for the initial request, and subsequent calls to p.then will receive the same result: the response from the first page request.

I made some adjustments to your code and tested it with a simulated interface:

const apiResult2 = async (path: string, objectName: string, params: any = { }) => {
    const fetchData = async () => new Promise<any> ((resolve, reject) => {
        gapi.load('auth2:client', () => {
            gapi.client.request({
                path: path,
                params: params
            }).then(response => {
                // Resolve this promise with the first key in the response object.
                resolve(response.result);
            }, reason => {
                console.log(reason);
                reject(reason.result);
            });
        });
    });

    let returnArray: string[] = [];
    do {
        const data = await fetchData();

        if (data.hasOwnProperty(objectName)) {
            for (let obj of data[objectName]) {
                returnArray.push(obj);
            }
        }

        if (data.hasOwnProperty('nextPageToken')) {
            params.nextPageToken = data.nextPageToken;
        } else {
            params.nextPageToken = null;
        }
    } while (params.nextPageToken);

    return returnArray;
}

Example usage:

apiResult2(path, objectName, params).then(
    result => console.log(result),
    err => console.log('error', err)
);

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

React, Storybook - Error TS2307: Button module not found or its type declarations. Can Storybook resolve this issue?

In my React project, I have a Button component created with "create-react-app" that uses absolute paths for importing. When trying to import { Button, ButtonProps } from 'Button', I encountered an error with TS2307. The absolute path 'Butto ...

I am encountering an issue where JSON.parse is returning undefined when trying to

Upon receiving a string from my server, I am attempting to parse it into a JSON object. Here is the string and relevant code snippet: stringToParse = "\"{'female': 16, 'brand': 75, 'male': 8}\"" d ...

What is the process for sending a post request with a JSON payload to an external API using Node.js?

I am currently facing an issue while attempting to send a POST request with a JSON payload to an external API using node.js. Below is the code I am using: var express = require('express'); var bodyParser = require('body-parser'); var ...

The issue I am facing is that when I click on a checkbox, only one of them seems to respond

When I click the button, only the first checkbox event is being checked while the rest of them are not. Can someone please provide some guidance on how to fix this issue? $("#cascadeChange").click(function() { //alert("Clicked"); ...

Is there an alternative course of action since determining if Observable is empty is not feasible?

I am diving into Angular 11 and exploring the world of Observables and Subjects as a beginner. Within my application, I have a mat-autocomplete component that organizes its results into categories. One of these categories is dedicated to articles, and I&a ...

Swapping out a subarray within an array containing objects with a fresh array consisting of objects

Here is the structure of my data document: { "_id": "6287a6c5975a25cc25e095b0", "userName": "Robot", "projectName": "TestProject", "projectTypeName": "fixed project", "pro ...

Exploring the data types of dictionary elements in TypeScript

I have a model structured like this: class Model { from: number; values: { [id: string]: number }; originalValues: { [id: string]: number }; } After that, I initialize an array of models: I am trying to compare the values with the o ...

What is the best way to dynamically insert values into a JSON object?

I'm currently working with a JSON object in Angular and I need to dynamically add values that the user enters. Despite searching extensively, I haven't found a straightforward method to achieve this. I simply want to understand how to append key- ...

How to use Javascript, HTML5, and AngularJS to display and print a PDF document within a

I have a situation where I need to load a Base64 encoded PDF as a String from my server into JavaScript in my client application which is built using AngularJS and HTML5. The structure of my HTML code is as follows: <div id="printablePdfContainer"> ...

The slicing of jQuery parent elements

Hey there! I recently created a simulated "Load More" feature for certain elements within divs. However, I've encountered an issue where clicking on the Load More button causes all elements in both my first and second containers to load simultaneously ...

Track the number of books read per month using an array of objects

Consider the following array of objects: const sampleArray = [{"read":true,"readDate":2021-01-15T18:21:34.059Z}, {"read":true,"readDate":2021-01-15T18:21:34.059Z}, {"rea ...

Is there a way to dynamically create a property and assign a value to it on the fly?

When retrieving data from my API, I receive two arrays - one comprising column names and the other containing corresponding data. In order to utilize ag-grid effectively, it is necessary to map these columns to properties of a class. For instance, if ther ...

The Node function will yield a BluebirdJS Promise

I've encountered a minor issue with this script. While it functions properly, the "runTenant" method is not returning a promise that needs to be resolved with "all()". Here's the code snippet in question: Promise.resolve(runTenant(latest)).then ...

Locating a class variable using a string chosen from a DropDown menu

In my Tv class, I have several string variables. One requirement is for the user to select an option from a DropDown list and input a value. This entered value should then be stored in the Tv class under a variable with a similar name to the selected optio ...

Exploring the possibilities in Bootstrap 5.3: Modifying the maximum width of an individual tooltip

Is there a way to modify the maximum width of a specific Bootstrap Tooltip without affecting the others? I do not utilize Sass or SCSS, and have attempted various methods outlined in the documentation: tooltip-max-width="300px" bs-tooltip-max-wid ...

Export problem in TypeScript

I'm having trouble with exporting in the prisma TypeScript file while executing it within a Node.js GraphQL project. Here is the error I am encountering: 05-12-2018 18:20:16: SyntaxError: /home/user/Publish/PracticeBusiness/src/generated/prisma.ts: ...

Quick + Vue Router - Lazy Loading Modules

For my personal project, I am using Vite alongside Vue 3 and have integrated vue-router@4 for managing routes. Since all of my modules share the same set of routes, I created a helper function: import { RouteRecordRaw } from 'vue-router' import p ...

Swapping values in JSON by comparing specific keys: A guide

I have JSON data that contains a key called reportData with an array of values: {"reportData":[ ["1185","R","4t","G","06","L","GT","04309","2546","2015","CF FE","01H1","20","23840","FF20"], ["1186","R","5t","R","01","L","TP","00110","1854","2016" ...

Avoid showing images when the link is not working

I am dynamically fetching images and displaying them on my webpage. return <div className="overflow-hidden "> <Image className="relative w-full h-40 object-cover rounded-t-md" src={cover_url} alt={data.name} ...

Using TypeOrm QueryBuilder to establish multiple relations with a single table

Thank you for taking the time to read and offer your assistance! I am facing a specific issue with my "Offer" entity where it has multiple relations to "User". The code snippet below illustrates these relationships: @ManyToOne(() => User, (user) => ...