Reputation: 3417
The code below is returning [Promise, Promise, Promise, Promise, Promise]
and I'm not sure what I'm doing wrong here. What am I missing in this async function?
async function testFunction(page) {
async function multipleTests(test) {
const tests = Array.from(test.querySelectorAll("li"));
const allTests = tests.map((test, index) => {
return {
title: test.querySelector("h3").innerText
};
});
return allTests;
}
const tests = Array.from(document.querySelectorAll("section.test")).map(async test => {
if (test.querySelector("ul li")) {
const tests = await multipleTests(test);
return tests;
}
})
console.log(tests);
}
Upvotes: 0
Views: 142
Reputation: 707318
First off, assuming this is normal browser code, I don't see anything in the .map()
part of the function that is asynchronous at all. So, you shouldn't be using async
there.
Second, ALL async functions return a promise. So when you do this:
const allTests = test.map(async () => {...});
You will ALWAYS end up with an array of promises. If you want to get the values from those promises, you would have to use Promise.all()
as in:
const allTests = Promise.all(test.map(async () => {...});)
But, if nothing in the .map()
callback is asynchronous, then there is no need for promises or async
here at all - remove the async
from the .map()
entirely.
const allTests = test.map(() => {...});
Then, third in the second .map()
, it again looks like everything is synchronous. I think you can simplify all the code to synchronous like this:
function testFunction(page) {
function multipleTests(test) {
const tests = Array.from(test.querySelectorAll("li"));
const allTests = tests.map((test, index) => {
return {
title: test.querySelector("h3").innerText
};
});
return allTests;
}
const tests = Array.from(document.querySelectorAll("section.test")).map(test => {
if (test.querySelector("ul li")) {
return multipleTests(test);
} else {
// return something else here or your tests array will have an undefined value
}
})
console.log(tests);
}
Some points of advice to consider:
async
, await
or promises in segments of purely synchronous code. While async/await
helps people write asynchronous code more easily than without, you're still dealing with promises and getting all results with await
or eventually with .then()
whereas synchronous code can just return or compute a value directly.async
functions return a promise. Always. The calling code will have to use await
or .then()
on the returned promise to get access to the value..map()
(long with all the array iterator methods) is NOT async
or promise saavy. So, when you declare an async
callback for .map()
that callback always returns a promise so you always end up with an array of promises. Sometimes that's useful and what is needed, but you will then have to use something like Promise.all()
to know when all those promises have resolved and when you can get all their values.async
and await
in a plain for
loop because the for
construct starting in ES6 is await
saavy and it will pause the loop for await
making your code much simpler to write.tests
computation in the second part of the function looks like odd logic. You first do a document.querySelectorAll("section.test")
and then you again look for test.querySelector("ul li")
. It seems like you could just do one selector originally document.querySelectorAll("section.test ul li")
and avoid two separate operations.Upvotes: 3