Title rewritten as: Recursive async function cannot return value
P粉729518806
2023-08-29 21:11:13
<p>I'm making a recursive async function that is running a mysql query. This is the database I'm using: </p>
<pre class="brush:php;toolbar:false;"> ---- ------------------- ---------- - ---------- ---------- -----------------------
| id | task | completed | parentid | createdby | createdat |
---- ------------------- ----------- ---------- ------ -----------------------------
| 1 | Clean Apartment | 0 | NULL | 1 | 2022-03-24 00:47:33 |
| 2 | Clean the bathroom | 0 | 1 | 1 | 2022-03-24 00:47:33 |
| 3 | Clean the kitchen | 0 | 1 | 1 | 2022-03-24 00:47:33 |
| 4 | Take a shower | 0 | 2 | 1 | 2022-03-24 00:47:33 |
| 5 | Wash the toilet | 0 | 2 | 1 | 2022-03-24 00:47:33 |
| 6 | Cleaning glass panes | 1 | 4 | 1 | 2022-03-24 00:47:33 |
| 7 | Clean faucets | 0 | 4 | 1 | 2022-03-24 00:47:33 |
| 8 | Clean the sink | 0 | 3 | 1 | 2022-03-24 00:47:33 |
| 9 | Take out the trash | 1 | 3 | 1 | 2022-03-24 00:47:33 |
---- ------------------- ----------- ---------- ------ ----- --------------------- </pre>
<p>If I store this database in an array, I can run this function: </p>
<pre class="brush:php;toolbar:false;">function comp(tasks, taskId) {
var task = tasks.find(task => task.id === taskId)
var children = tasks.filter(t => t.parentId === taskId)
task.children = children.map(child => comp(tasks, child.id));
return task
}</pre>
<p> to recursively nest subtasks into the main task. </p>
<p>The problem is that I don't understand asynchronous functions well enough.</p>
<p>This is my progress so far: </p>
<pre class="brush:php;toolbar:false;">async function comp(taskId) {
// SELECT * FROM tasks WHERE id = taskId
var task = await con.promise().query('select * from tasks where id = ' taskId)
// SELECT * FROM tasks WHERE parentId = taskId
var children = await con.promise().query('select * from tasks where parentid = ' taskId)
task[0][0].children = children[0].map(child => {
comp(child.id)
})
console.log(task[0])
}</pre>
<p>But this returns a task with undefined subtasks: </p>
<pre class="brush:php;toolbar:false;">[
{
id: 1,
task: 'Clean the apartment',
completed: 0,
parentid: null,
createdby: 1,
createdat: 2022-03-23T23:47:33.000Z,
children: [ undefined, undefined ]
}
]</pre>
<p>In a nutshell, what I want is the following: </p>
<pre class="brush:php;toolbar:false;">{
id: 1,
task: 'Clean the apartment',
completed: 0,
parentid: null,
createdby: 1,
createdat: 2022-03-23T23:47:33.000Z,
children: [
{
id: 2,
task: 'Clean the bathroom',
completed: 0,
parentid: 1,
createdby: 1,
createdat: 2022-03-23T23:47:33.000Z,
children: [
{
id: 4,
task: 'wash shower',
completed: 0,
parentid: 2,
createdby: 1,
createdat: 2022-03-23T23:47:33.000Z,
children: [ ... ]
},
{
id: 5,
task: 'wash toilet',
completed: 0,
parentid: 2,
createdby: 1,
createdat: 2022-03-23T23:47:33.000Z,
children: [ ... ]
},
]
},
{
id: 3,
task: 'Clean the kitchen',
completed: 0,
parentid: 1,
createdby: 1,
createdat: 2022-03-23T23:47:33.000Z,
children: [ ... ]
},
}</pre>
<p>Any suggestions? </p>
You are waiting for the original two expected items to finish running before starting the next recursive call and then printing without waiting for the recursive call itself.
First, you need
But you also need to wait for each child to finish running.
will wait for each promise in the array you pass it to complete, while
children[0].map(async () => {})
will return an array of promises. Just keep waiting for it and you should be fine.Actually, the only problem with your code is that you are not waiting for the result from the async function
comp()
.map()
will return an array of Promise, you need to wait for all these Promise, you can usePromise.all()
to achieve this.Promise.all()
Returns a Promise that will be resolved when all Promises in the array passed toPromise.all()
have been resolved. If you wait for it, your children array will be propagated as you expect.This is the code using
Promise.all()
. Since I don't currently have a proper database ready, I replaced all of your database async calls with an asynchronous call to a function with an artificial delay so you can see how the calls are being waited for and whether the results are actually being waited for.