Mackbear
Mackbear

Reputation: 21

Can I have a sequence of events kick in on javascript .click function?

Good day!

I have sequence of events I would like to happen in order within an onclick function of JavaScript. However, when I add a couple of .post functions that updates a db, it does not work. Is it not possible to have more than 1 .post functions within an onclick function? Here's my code, adding some more text here as the site won't let me post saying I need to add more details because I have posted mostly code. Please help, looking forward to your assistance

$('#vesmos').click(function(){
    var dt = new Date();
    var dformat = dt.getFullYear() + "/"
                + (dt.getMonth()+1)  + "/" 
                + dt.getDate()  + " "  
                + dt.getHours() + ":"  
                + dt.getMinutes() + ":" 
                + dt.getSeconds();
    //set start and end date on form fields
    if($.trim($('#stdt').val()) == ''){
        $('#stdt').val(dformat);
     }

    $('#enddt').val(dformat);

    //update rt table close rt log (code does not when I add this function)
    $.post("closert-docadminus.php",
    {
        empname: $("#empname").val(),

    });

    //calculate start and end date
    var strt = $('#stdt').val();
    var end = $('#enddt').val();

    var d2 = new Date(strt);
    var d1 = new Date(end);
    $('#insec').val(parseFloat(((d1-d2)/1000).toFixed(2)));
    $('#inmin').val(parseFloat(((d1-d2)/60000).toFixed(2)));
    $('#inhrs').val(parseFloat(((d1-d2)/3600000).toFixed(2)));

    //save to ams table logs
    $.post("savesettings.php",
    {
        empname: $("#empname").val(),
        task: $("#task").val(),
        dttoday: $("#dttoday").val(),
        stdt: $("#stdt").val(),
        enddt: $("#enddt").val(),
        insec: $("#insec").val(),
        inmin: $("#inmin").val(),
        inhrs: $("#inhrs").val(),
        pltform: $("#pltform").val(),

    });

    //clear textboxes
    $('#stdt').val("");
    $('#enddt').val("");
    $('#task').val("");
    $('#pltform').val("");


    //fill textboxes
    $('#task').val("Mail Open/Sort");
    $('#pltform').val("VES");
    $('#stdt').val(dformat);
    $('#statype').val("Occupancy");
    $('#statprio').val("Primary");

    // save log to rt table (code does not when I add this function)
    save to realtime
    $.post("savert-docadminus.php",
    {
        empname: $("#empname").val(),
        task: $("#task").val(),
        stdt: $("#stdt").val(),

    });
});

Upvotes: 0

Views: 166

Answers (3)

Jorge Chayan
Jorge Chayan

Reputation: 26

Given that the OP clarified in the comments section that 'the problem' is: Dispatching the XHRs sequentially one after another, I'm adding a second answer on how to achieve it, but first, I'm going to try to explain in brief why adding a $.post call after another doesn't work.

XMLHTTPRequests are asynchronous by default. This forces you to think in an asynchronous domain and assume that calling:

asyncFunction1() ($.post)
asyncFunction2() ($.post)

doesn't mean that asyncFunction2 will be executed when asyncFunction1 ends its execution

  1. This doesn't mean that JavaScript is parallel - multi-threaded. JavaScript is single-threaded and asynchronous, it uses an event loop for resolving code execution. Learn more about it here.
  2. Ajax (XMLHTTPRequests - $.post) is a feature that is browser specific... The browser might open a separate thread in order to send the request but it doesn't really matter because remember, at the programming language level (JavaScript) we don't have threads.

Weird right, so back to the issue, What if we want to execute code right after an asynchronous function ends?

There are multiple patterns for achieving this:

  1. Callbacks
  2. Promises
  3. Async/Await

And typically, an asynchronous function should provide you with an API for doing this, at least a good old callback.

According to the jQuery.post ($.post) documentation, you can add a callback like this:

$.post('url', data).done(function (response1) {
    // Next code here
})

Which will lead you to:

$.post('url1', data1).done(function (response1) {
    // The first XHR finished successfully, we send the second
    $.post('url2', data2).done(function (response2) {
        $.post('url2', data2).done(function (response2) {
            // The second XHR finished successfully, we send the third and so on
            $.post('url3', data3).done(function (response3) {...})
        })
    })
})

Which will eventually lead you to say

"That code nesting doesn't look good and easy to maintain, how can I make it cleaner?"

Congratulations, you've entered the domain of Callback Hells

Upvotes: 0

Sebashish
Sebashish

Reputation: 61

You can have enormous events. This is not working because of asynchronous nature of Javascript. All the I/O calls are asynchronous, so third call can finish first but second call can finish last. You should learn more about Javascript Event loop.

Upvotes: 1

Jorge Chayan
Jorge Chayan

Reputation: 26

What you're trying to make is a set of concurrent XMLHTTPRequests

Depending on the browser, you're going to have a set of maximum concurrent XHRs, there's a list here. But even if they are too many, they will get queued and so the browser sends them in the future.

You are trying to make 3 concurrent XHRs in a click event handler, I don't see how that is a problem. Just saying 'it does not work' is not enough information on the problem, you need to dig and debug.

Here's what I recommend you to do:

1, Open the "Console" tab in the developer tools and check that you don't have any JavaScript errors in the console that prevent the XHRs from being dispatched.

2, Open the "Network" tab in the developer tools and check that the XHRs are effectively being dispatched; if they are, check what's the server response.

3, In your .post calls append .done and .fail callbacks in order to confirm what is the server responding, for example:

$.post("some.php", data: { name: "John", location: "Boston" })
  .done(function (response) {
      console.log(response);
  })
  .fail(function (jqXHR, textStatus, errorThrown) {
      console.log(textStatus);
      console.log(errorThrown);
  });

That should lead you to the root cause(s) of the problem

Upvotes: 0

Related Questions