31

Trying to learn the async pattern in Javascript but it doesn't appear that it waits for the following line. In the following example, the collection is the request object and not the actual parsed body. Isn't await supposed to wait for the request to finish?

async function importUsers(endpoint) {
    const options = {
        data: search,
        uri: endpointCollection,
        headers,
    }

    try {
        const collection = await browser.post(options, (err, res, body) => JSON.parse(body))
        // collection is the request object instead of the result of the request
        const users = await collection.data.forEach(item => parseUserProfile(item));

        await users.forEach(user => saveUserInfo(user))
    } catch(err) {
        handleError(err)
    }
}



async function parseUserProfile({ username, userid }) {
    const url = userProfileString(username)

    try {
        const profile = await browser.get(url, headers, (err, res, body) => {   
            return { ... } // data from the body
        })
    } catch(err) {
        handleError(err)
    }
}
user3162553
  • 2,699
  • 3
  • 37
  • 61
  • 2
    `await` only works with functions that return a promise. Looks like `browser.post` doesn't return a promise and `forEach` certainly does not return one (it doesn't return anything). – Felix Kling May 20 '17 at 19:50
  • Hmm, so I need to have nested calls such as `parseUserProfile` return a resolved promise object (or reject)? – user3162553 May 20 '17 at 19:51

2 Answers2

22

Async/Await only works on functions that return (and resolve) a promise.

The following example will write to the console after 3 seconds, and then continue on.

// Tell the browser that this function is asynchronous
async function myFunc() {
    // Await for the promise to resolve
    await new Promise((resolve) => {
        setTimeout(() => {
            // Resolve the promise
            resolve(console.log('hello'));
        }, 3000);
    });
    // Once the promise gets resolved continue on
    console.log('hi');
}

// Call the function
myFunc();

Without async/await, the output would be as follows:

hi
hello

Here is an example without async/await:

// Tell the browser that this function is asynchronous
async function myFunc() {
    // Skip await
    new Promise((resolve) => {
        setTimeout(() => {
            // Resolve the promise
            resolve(console.log('hello'));
        }, 3000);
    });
    // Since await was not used, this will print first
    console.log('hi');
}

// Call the function
myFunc();

This would be because the hi output would run and then after 3 seconds the timeout would run.

But with async/await, the output looks like this:

hello
hi

This is because we await for the timeout then we run the hi output.

Get Off My Lawn
  • 34,175
  • 38
  • 176
  • 338
7

await should expect a promise, for a callback style async function, you can transform it like:

new Promise((resolve, reject) => browser.post(options, (err, res, body) => resolve(JSON.parse(body))))

For an array, you need to map it to an array of promises, then use Promise.all to turn it to a 'promise of array', for example:

Promise.all(collection.data.map(item => parseUserProfile(item)))
rstar
  • 1,006
  • 1
  • 8
  • 14