Search code examples
javascriptnode.jsrecursionuser-inputstack-overflow

Programming repeated user interaction via recursion in Nodejs


I am currently learning javascript with Nodejs and I am working on a small program that repeatedly asks the user for input and generates text after the user presses enter.

To achieve this, I first thought of using a single function for my main program flow, that changes its behaviour based on the status parameter. This also means, that I am recursively calling this function with a different status and wait for user input inbetween these calls.

It appears to work fine, but I know that repeated recursion can cause problems in some situations. I was wondering, if this is such a situation, where theoretically if the user keeps interacting with the dialogue for a long time, eventually this approach would cause a stack overflow.

async function start(status) {
    switch (status) {
        // StartMenu
        case 0:
            let input1 = await waitForInput(["1", "2", "3", "exit", "quit"]);
            if (["exit", "quit"].includes(input1)) {
                return start(2);
            } else {
                doSomething(input1);
                return start(1);             
            }
        // Something 
        case 1:
            let nextAction = await waitForInput(["", "back", "exit", "quit"]);
            switch (nextAction) {
                case "":
                    doSomethingElse();
                    return start(1);
                case "back":
                    return start(0);
                case "exit":
                case "quit":
                    return start(2);
            }
            break;
        // Exit/ Quit
        case 2:
            console.log("Program exiting...");
            break;
        default:
            console.log("Error: invalid status");
            break;
    }
}

start(0);

Solution

  • This also means, that I am recursively calling this function.

    This is not a real case of recursion. When the await operator is executed, the function returns. When the awaited promise resolves, the function's execution context is restored, but that execution will be resumed from the event loop, so there is no build up of a call stack, except for one extra level when the next call to start is made. But as stated above, that recursive call returns when the await operator is evaluated, reducing the call stack before any subsequent call of start is made.

    There is however a chain of linked-in promises that builds up, but as this only grows with the rate of the number of manual inputs, using heap memory, this is not going to be a problem in practice.

    On the other hand, you might consider using an iterative approach.