简体   繁体   中英

Async / Await, how do I force my function to wait until promise is resolved before it continues?

I would like my function to execute until the nextPageToken is null. When I execute the function the first time, it waits for the promise to be resolved. However as soon there is a nextPageToken present on the response, the function does not wait for the response and a stack overflow occurs.

It seems that f() is not suspended on the when await p.then() is called.

Am I totally misunderstanding how async/await works?

Any help 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;
  }

If your function needs to "await" some async call, then it must also be async. Your function apiResult2 is not going to wait for f to be finished, in order to return returnArray .

EDIT:

The main issue here is that you are trying to reuse the promise p to make different requests, but this is not possible. The promise p will be initialized with the parameters for the first request, and all the calls to p.then will be fulfilled with the same result: the response for the first page request.

I made some small changes to your code, and got it working with a mocked interface:

const apiResult2 = async (path: string, objectName: string, params: any = { }) => {
    const requestPage = 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 page = await requestPage();

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

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

    return returnArray;
}

Usage example:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM