Search code examples
javascriptasync-awaitelectronpromptsynchronized

Async function with sync user prompt


I'm trying to get a sync user prompt in my electron app to work. To be more exact, I have an object with a set of commands and template variables.

I want to replace all unknown template variables with a user input... synchronously. So that the commands are only sent after all my variables have been replaced.

Can you please help me?

This is how I call a sync user prompt (bootstrap modal with a form) on my side (this test is working and I receive the result synchronously after the user put something in the prompt):

async function test(gui) {
    const result = await gui.syncPrompt('User question')
    console.log('result:', result)
}
test(this.gui)

My problem is, I'm very confused with all the async/await statements and I don't know how I could include this in my normal replacing process? What I got so far:

const obj = {
    cmds: [
        'port {port}',
        'template1 {temp1} und template2 {temp2}',
        'template2 {temp2} und template1 {temp1}'
    ]
}

const templatePrompt = async () => {
    const map = {}
    await obj.cmds.forEach(async (element, index, array) => {
        const patt = /{.*?}/gmi
        patt.lastIndex = 0
        if (patt.test(element)) {
            await obj.cmds[index].match(patt).map(async (value) => {
                let userInput = map[value]
                if (!userInput) {
                    // Create Prompt here.
                    // userInput = Math.random() * 10
                    userInput = await this.gui.syncPrompt('User question:')
                }
                map[value] = userInput
                return true
            })
            await Object.keys(map).map(async (key) => {
                obj.cmds[index] = obj.cmds[index].replace(key, map[key])
                return true
            })
        }
    })
}
await templatePrompt()
console.log(obj)

I forgot to mention that my real problem is... the function templatePrompt() is running and my first prompt is showing up. In the meantime, bevor the user even typed some input, the hole process is already completed without replacing the template varibales. :( My goal is to achive a "pause" on every prompt.


Solution

  • The following code simulates waiting for user input from a sequence of prompts.

    Simply use an async function, a for loop and await each response.

    const random = (arr) => arr[~~(Math.random()*arr.length)]
    
    const simulatedNamePrompt = () => 
        new Promise((resolve) => 
            setTimeout(() => resolve(random(['Ben', 'Sam', 'John'])), 1500))
    
    const simulatedAgePrompt = () => 
        new Promise((resolve) => 
            setTimeout(() => resolve(random(['19', '20', '21'])), 1500))
    
    const questions = [
        {
            question: 'What is your name?',
            prompt: simulatedNamePrompt
        },
        {
            question: 'What is your age?',
            prompt: simulatedAgePrompt
        }
    ]
    
    async function askUserQuestions(questions) {
        const responses = []
        for(const { question, prompt } of questions) {
            console.log(`Asking "${question}"`)
            const response = await prompt()
            responses.push(response)
        }
        console.log(responses)
    }
    
    askUserQuestions(questions)