0

I'm having some trouble. I'm trying to execute my ajax function 1 by 1, not all at the same time. I'm using promise but I have no more idea on how to achieve it. Here is my code :

function run_action(action){
    if(action == "login"){
        return $.ajax({
            url: "login.php",
            type: "post",
            data: {password: password},
            beforeSend: function() {
                console.log('beforeSend login');
            },
            success: function (response) {
                console.log('Success Login');
            },
            error: function (request, error) {
                console.log('Error Login');
            },
        })
    }
    if(action == "register"){
        return $.ajax({
            url: "register.php",
            type: "post",
            data: {password: password},
            beforeSend: function() {
                console.log('beforeSend register');
            },
            success: function (response) {
                console.log('Success Register');
            },
            error: function (request, error) {
                console.log('Error Register');
            },
        })
    }
}

var actions = ['register', 'login'];
services.forEach(checkActions);
function checkActions(item, index) {
    if (document.getElementById(item).checked) {
        var promise = run_action(item);
        promise.success(function (data) {
            console.log('Run after');
        });
        console.log('Run first')
    }
}

In this case login and register are both launched at the same time, login doesn't wait for register to finish so he can start processing.

executable
  • 3,365
  • 6
  • 24
  • 52

3 Answers3

1

In case you can't properly wait for checkActions from the outside, you could maintain a task queue for that:

 let queue = Promise.resolve();

 function checkActions(item, index) {
    queue = queue
     .then(() => run_action(item))
     .then(() => {
       console.log("Next item was processed", item);
       // Your code here
     });
   // Synchronous code here - This won't execute in order!
 }
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
0

Currently your code runs through the forEach loop with each action and invokes checkActions with that action, thus firing the request. Array.prototype.forEach executes synchronously (without any kind of check to the promises returned by $.ajax). The following would wait for 'register' to finish before firing 'login':

function checkActions(item) {
  if (document.getElementById(item).checked) {
    return run_action(item);
  }
}

checkActions('register')
  .then(data => {
    return checkActions('login');
  });

I'm not super familiar with jQuery's promise structure, so I used .then, but I believe you can use .success without issue as well.

Unrelated comment, your run_actions function should really be split into two functions (login and register) since they are completely unrelated aside from the fact that they are making requests.

mb_s88
  • 392
  • 1
  • 12
0

First- its not a good practice to trust a order-based function (AKA - run them by the array order), run your functions according to logic.

For example: if the first function was failed - you dont want to run the next functions in the array.

If you consist to run the functions in array - you can use an async

async function runActions( actionsList ) {
  for(const action of actionsList) {
    await run_action( action );
  }
};

In general - we use the then method to run anther function when specific promise is done. Like so:

promise.then( onSuccess => {
   // try to log in
}, onFail => {
   // tell the user the signup was failed
});

BTW - you can use the native fetch instade of jQuery ajax, and get simple to use, promise-based way to communicate with your sever.

Like so:

fetch("login.php" , {
  method: 'POST', // or 'PUT'
  body: {password: password}, // data can be `string` or {object}!
  headers:{
    'Content-Type': 'application/json'
  }
}).then( ... )
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
Elad
  • 2,087
  • 1
  • 16
  • 30
  • I don't have only login, register function, I have plenty, it won't work in my case – executable Aug 12 '19 at 09:29
  • @executable It doesn't matter what you do within your success function, you can call a function inside an Array at location of I, the logic is the same. – Elad Aug 12 '19 at 09:37
  • @executable and BTW - Its not a good practice to trust a order-based function, run your functions according to logic. Don't look for shortcuts – Elad Aug 12 '19 at 09:39
  • Hmm ok, do you mind to post an example with more function in the main idea like register or login – executable Aug 12 '19 at 09:54
  • And how do you use it in my `foreach` loop ? – executable Aug 12 '19 at 10:03
  • @executable again, its not a good practice, but i edited my answer anyway. you can look for more information here: https://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence – Elad Aug 12 '19 at 10:14