2

I'm trying to stop a form from automatically submitting, then use JavaScript to replace the form with text telling the user the server is processing the form, and in the callback in my 'post' route on the server the user gets sent to the results page after some processing finishes with information from the form. But before the span can appear in the HTML the form has already been submitted and the page is waiting for a response from the server. If I insert a timeout function I can force the span element to appear before the form gets submitted, but there's got to be a better way to do this. I tried using async await .then() but that also didn't work - maybe loading the span can't finish rendering before the form is submitted? - Thanks

HTML and JS:

var proc = async () => {
    var form = document.getElementById('form');
    form.style.display = 'none';
    var span = document.getElementById('testSpan');
    span.style.display = 'block';

    //using this timeout I can get the span element to appear
    //window.setTimeout(() => {
        //document.getElementById('form').submit()
    //}, 500);
}

var btn = document.getElementById('submitBTN');

btn.addEventListener('click', async () => {
    await proc().then(document.getElementById('form').submit());
})
<span style='display : none' id="testSpan">processing...</span>
<form method="POST" action="/submit-form" id="form" onsubmit="event.preventDefault();">
    <input required id="linkInput" type="text" name="name" />
    <input id='submitBTN' type="button" value="Submit"/>
</form>
robyaw
  • 2,274
  • 2
  • 22
  • 29
  • because you are calling the submit method and what it returns is assigned to the then.... `.then(() => document.getElemen....` – epascarello Feb 24 '21 at 00:50
  • Thanks for the response. Okay, your response made me think I should use ```return document.getElementById('form').submit();``` at the end of ```proc()``` and that will pass it to .then() But form.submit() still occurs before the span appears. What am I misunderstanding? – Dillon Meyer Feb 24 '21 at 01:05
  • Yes, javascript must stop for the browser to render your span before you submit. And yes, you're right: the only way to make it stop, render then go is with `setTimeout(submit, 0)`. Like rendering, promise from an await can't come before your script stop running somewhere. – denis hebert Feb 24 '21 at 01:52
  • 1
    Oh, I missed the fact there is no actual asynchronous code in your method.... That is not going to have a promise. – epascarello Feb 24 '21 at 02:08

2 Answers2

0

If you want to continue processing after posting to server and before showing its resulting page, Ajax is the easiest way to go. Normally, people rather preprocess before posting and then let the server init a new page almost right away.

Ether way, in the interval, to render any new showing during a running process or preprocess, you must make that running stop and go. The easiest way to do so is with the trick of the setTimeout of 0 ms: you modify what you want to show, do a setTimeout of the remaining process and end that main process; a bit like:

// Change to display
form.style.display = 'none';
span.style.display = 'block';
// Put the remain of process as an after rendering
setTimeout( () => {
  // remaining process
}, 0 );
// End of main process, so the browser renders

If you want to render many times during the process, I would refer you to a more complete answer here.

denis hebert
  • 128
  • 10
0

Using async and await does not make things into promises. You are going to have to return a promise to use a promise.

In your cause, you are still going to have to use a timeout. In the end it is not really different than you just calling the submit in the timeout.

var proc = async() => {
  document.body.classList.add("submitting");
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, 500);
  });
}

var btn = document.getElementById('submitBTN');
btn.addEventListener('click', () => {
  proc().then(() => document.getElementById('form').submit());
})
#testSpan,
.submitting form {
  display: none;
}


.submitting #testSpan {
  display: block;
}
<span id="testSpan">processing...</span>
<form method="POST" action="/submit-form" id="form" onsubmit="event.preventDefault();">
  <input required id="linkInput" type="text" name="name" />
  <input id='submitBTN' type="button" value="Submit" />
</form>
epascarello
  • 204,599
  • 20
  • 195
  • 236