Как правильно обрабатывать вложенные асинхронные вызовы ожидания в Node?

Попытка изучить асинхронный шаблон в Javascript, но не похоже, что он ждет следующей строки. В следующем примере коллекция является объектом запроса, а не фактически проанализированным телом. Разве await не должен ждать завершения запроса?

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

person user3162553    schedule 20.05.2017    source источник
comment
await работает только с функциями, которые возвращают обещание. Похоже, browser.post не возвращает обещание, а forEach уж точно не возвращает (ничего не возвращает).   -  person Felix Kling    schedule 20.05.2017
comment
Хм, так мне нужно, чтобы вложенные вызовы, такие как parseUserProfile, возвращали разрешенный объект обещания (или отклоняли)?   -  person user3162553    schedule 20.05.2017


Ответы (2)


Async/Await работает только с функциями, которые возвращают (и разрешают) обещание.

Следующий пример запишет в консоль через 3 секунды, а затем продолжит.

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

Без async/await вывод будет следующим:

hi
hello

Вот пример без 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();

Это было бы связано с тем, что вывод hi будет запущен, а затем через 3 секунды будет запущен тайм-аут.

Но с async/await вывод выглядит так:

hello
hi

Это потому, что мы ждем тайм-аута, а затем запускаем вывод hi.

person Get Off My Lawn    schedule 20.05.2017
comment
В порядке. Это имеет большой смысл. Похоже, что async/await — это стратегия предотвращения вложенных промисов, но не их удаления. - person user3162553; 20.05.2017
comment
Да, в основном это помогает остановить/предотвратить callback hell google.com/search?q= javascript+обратный вызов+ад - person Get Off My Lawn; 20.05.2017

await следует ожидать обещания, для асинхронной функции обратного вызова вы можете преобразовать ее следующим образом:

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

Для массива вам нужно сопоставить его с массивом обещаний, а затем использовать Promise.all, чтобы превратить его в «обещание массива», например:

Promise.all(collection.data.map(item => parseUserProfile(item)))
person Sheng    schedule 20.05.2017