Performing 2 successive tasks when a HTML form is submitted (using Ajax and a server made with Express in Node.js)

StackOverflow https://stackoverflow.com/questions/23618810

Вопрос

I have an input form in a HTML file:

<form id="urlarticle">
      <input type='text' name='thislink'>
      <input type='submit' value='Select'>
</form>

I want, when the submit button is clicked, 2 things to happen, in this order:

TASK 1: Make a POST request to a server, in order to enter new data in a database. Actually it is already working with the following code on the front-end:

<script type='application/javascript'>
        $("#urlarticle").submit(function() {
        $.ajax({
            type: "POST",
            url: "/selection/yes",
            data: $("#urlarticle").serialize(), 
            success: function(data)
            {alert(data); 
            }
        });
        return false; 
      });     
</script> 

...and with the following code on the back-end (server made with Express in Node.js):

app.post('/selection/yes', function(req, res) {
  link = req.body.thislink;  
  // part omitted here: function that do several things and then save some data to a database
});

TASK 2: Open a new window, rendered with an EJS view following a GET request on the server-side. TASK 2 has to be performed after TASK 1, because it uses the data saved in the database by TASK 1.

The code on the front-end should look like this:

<script type='application/javascript'>
    $("#urlarticle").submit(function() {
    var linkValue = $('input[name="thislink"]').val();
    window.open('/selection/yes/?value='+linkValue);
    });
</script>

...and the task is ready to be handled on the back-end:

app.get('/selection/yes/', function(req, res) {
    var thislink = req.param("value");
    // parts omitted here
    res.render('selection_form.ejs'); 
    });
});

But how can I make this TASK 2 to be executed only after TASK 1 is done? Thank you for your help!

Это было полезно?

Решение

I've created a sample NodeJS application that uses a lot of the same concepts (using Express and some jQuery on the client-side).

WORKING EXAMPLE: http://runnable.com/U3JEKcrGzPc1V8eQ/promises-w-bluebird-for-node-js-and-express

Using a basic Express application where an initial form is rendered using EJS (this is the GET request on /). Form submissions return a POST request to the same URL and are handled with a 2s delay to simulate a database action.

/**
 * Create a global storage variable as a example of an 
 * attached local database
 */
GLOBAL.linkStorage = [];

app.route('/')
  .post(function(req, res){
    console.log("Submission: " + req.body);
    GLOBAL.linkStorage.push(req.body.link);
    renderDelayedResponse(res);
  })
  .get(function(req, res){
    res.render('form.ejs');
  });

app.route('/2')
  .get(function(req, res) {
    // No need to pass in GLOBAL.linkValue since it's checked automatically
    res.render('submission.ejs');
  });

/**
 * Delay the response by a few seconds to simulate a database
 * create/update action
 */
function renderDelayedResponse(respWriter) {
  setTimeout(function() {
    GLOBAL.viewCount++;
    respWriter.send('Action Completed');
  }, 2000);  
}

There are going to be problems with calling window.open() after an asynchronous action, the popup blocker fires in all cases through my tests. To workaround this, you can see that the example has an embedded IFRAME that refreshes (after the 2 second database save completes) and displays the submitted value.

The complexity is mostly handled through jQuery where the IFRAME refresh occurs after we know that the POST request has submitted:

<!doctype html>
<html>
  <head>
    <style>
      .busy {
        cursor: wait !important;
      }
    </style>
    <script type="text/javascript" src="http://code.jquery.com/jquery-git.js"></script>
    <script type="text/javascript">
      $('document').ready(function () {

        function refreshViewer() {
          window.open("/2", "viewer");
          document.getElementById('submissionFrame').contentWindow.location.reload(true);
        }

        $('form input#submitLink').on('click', function () {
          var linkValue = $('input#link').serialize();
          $('body').addClass('busy');
          $.post('/', linkValue)
            .done(function(data) {              
              $('body').removeClass('busy');
              $('input#link').val('');
              refreshViewer();
            });           
          return false;
        });
      });
    </script>
  </head>
  <body>
    <div class="container">
      <form id="urlarticle" method="POST">
        <input type="text" name="link" placeholder="Link" id="link" />
        <input type="button" value="Submit" id="submitLink" />
      </form>

      <iframe id="submissionFrame" src="/2" seamless="seamless" width="50%" style="margin-top:100px">

      </iframe>
    </div>
  </body>
</html>
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top