1

I am creating an array JSONs with some test names and questions that are fetched from a database as follows:

db.all(sql_instruction, [], (err, rows) => {
        if (err) {
            console.log(err)
        }

        rows.forEach(test=>{
            let test_name = test.test_name;
            let question_array = [];
            sql_instruction = `SELECT * from questions where test_id = ?`;
            db.all(sql_instruction, [test.id], (err, rows) => {
                if (err) {
                    console.log(err);
                }
                rows.forEach(question=> {
                    question_array.push(question);
                });
                test_array.push(JSON.stringify({'test_name':test_name, questions:question_array}));
            });
        });
    });

If I try to access the variable 'test_array' outside the first db.all(), I would get an empty array because the async nature of the function.

What would be the best way to 'wait' for the completion of the 'test_array' variable to use it further in the application?

1 Answer 1

3

We can use Promise and async/await sugar syntax to make an asynchronous code looks like synchronous one. In the code below, I create a function getAllPromise to wrap the db.all method in a Promise. Then I can "wait" my getAllPromise function.

function getAllPromise(query, params) {
    return new Promise((resolve, reject) => {

        db.all(query, params, (err, rows) => {

            if(err) {
                
                // case error
                reject(err);
            }

            // "return" the result when the action finish
            resolve(rows);
        })
    })
}

async function getTestWithQuestions() { // your code

    try {
        let sql_instruction = ""; // your SQL query;
        const rows = await getAllPromise(sql_instruction, []);
        let test_array = [];

        for(let i = 0; i < rows.length; i = i + 1) {

            const test = rows[i];
            let test_name = test.test_name;
            let question_array = [];
            sql_instruction = `SELECT * from questions where test_id = ?`;

            const question_rows = await getAllPromise(sql_instruction, [test.id]);
            question_rows.forEach(question=> {
                question_array.push(question);
            });

            test_array.push(JSON.stringify({'test_name':test_name, questions:question_array}))
        }

        return test_array;

    } catch(error) {
        console.log(error);
        throw error;
    }
}

// using
// you need to add the keyword "async" in the function that call getTestWithQuestions, then :

const testWithQuestions = await  getTestWithQuestions(); // testWithQuetions is `test_array`

// if you don't want to add async keyword, then : 
getTestWithQuestions()
.then(testWithQuestions => console.log(testWithQuestions))
.catch(error => console.log(error));

You can find more information about callback, Promise and async/await here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.