1

I'm looking at trying to recreate the behavior of a basic prompt box in JavaScript so that I can style it. Essentially, I want to be able to call a function (window.vars.prompt) and have it prompt the user, then return the value the user inputted. I want everything to happen synchronously, so that I can call it via a function and have it returned to the caller.

What I have so far freezes the program, then crashes it. I know why, but i have no Idea how to fix it. Anybody fix it?

Thanks!

(function () {
    window.vars.userHasResponded = false
    window.vars.userResponse = ""
    window.vars.prompt = function(displayMsg) {
        $(".input").html(`<div class='prompt'><h2>${displayMsg}</h2><div class="input"><input id="promptValue"/></div><div class="promptContros"><button>ok</button><button>cancel</button></div></div>`)

        while (!window.vars.userHasResponded) {
            if (window.vars.userResponse)
                return window.vars.userResponse;
        }
    }
    window.vars.confirmPrompt = function() {
        $(".prompt").html("")
        window.vars.userResponse = $("#promptValue").val()
        window.vars.userHasResponded = window.vars.userResponse != "";
    }
})()

The HTML for the box is stored in a div with a class of input

Rohit Verma
  • 3,657
  • 7
  • 37
  • 75
J-Cake
  • 1,526
  • 1
  • 15
  • 35
  • how come that while loop doesn't work? It iterates and checks the condition? – J-Cake Jun 18 '18 at 06:59
  • @JacobSchneider Your while loop blocks browser interactions, it's synchronous. Your browser is trapped in infinite loop and hangs, user can't do anything – Justinas Jun 18 '18 at 07:01

2 Answers2

1

I'm looking at trying to recreate the behaviour of a basic prompt box in javascript...I want everything to happen synchronously, so that I can call it via a function and have it returned to the caller.

You cannot do so. prompt, alert, confirm, and beforeunload handlers are the only synchronous UI in the browser-based JavaScript world, and you cannot style them. It's impossible to replicate that behavior in your own UI widget.

Your own widget will have to be asynchronous.

In a comment on the question you've asked:

how come that while loop doesn't work?

Because the loop ties up the main UI thread by busy-waiting. User events in browser-based JavaScript queue up waiting for the thread to yield back to the browser (if the user even sees the updated DOM elements in the first place). Your busy-wait is keeping the current task active, meaning the events that follow it in the queue wait on your task to complete.

Instead, have your prompt and such return a Promise. Then, using it looks like this in a normal function:

prompt(/*...*/)
    .then(result => {
        // ...use the result
    });

...or like this in an async function:

const result = await prompt(/*...*/);

(Error handling omitted for brevity.)

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • @JacobSchneider - Not really; embracing the asynchronous, event-driven nature of browser-based programming isn't really all that hard. And these days, if you want to write synchronous-looking code, you can use [`async` functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function) and `await` (directly targeting only cutting-edge JavaScript engines, or via transpiling). – T.J. Crowder Jun 18 '18 at 07:03
  • Yeah, I'm just kinda new the whole `async` thing, and it's bit of a hassle to get involved. But I'll have a look. – J-Cake Jun 18 '18 at 07:04
1

I want everything to happen synchronously

Unfortunately, this is impossible - script-writers can't write their own APIs that basically block until they're resolved without freezing the browser completely, they can only invoke a few special built-in methods that have that peculiar property. As is, your while loop's thread will run forever, preventing confirmPrompt from ever running. The thread never ends and so never gives confirmPrompt a chance to run.

Try using Promises instead. await, while not synchronous, can look more synchronous than using .then.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320