0

I work with an application which sends some requests to server.

function createAjaxCall(data, done, fail) {
   return $.post("process_watch.php", data).then(done).fail(fail);
}

and

function step1() {
   return createAjax({ }, function(result) { console.log(result); return result; }, function() { });
}

function step2(res) {
   return createAjax({ }, function(result) { console.log(result); return result; }, function() { });
}

...

Some requests take a while (let's assume that I use sleep(1500); in PHP) and if I do:

step1().then((data) => step2(data)).then((data) => step3(data)) then will execute in same time.

What is going wrong ?

Snake Eyes
  • 16,287
  • 34
  • 113
  • 221
  • If I understand you correctly, then is nothing but syntactic sugar for callbacks. So for three calls it will take 1500*3 milliseconds – AL-zami Feb 06 '18 at 11:45
  • Ok, but how to make them `sync` ? For that I used promise. Or I missed something ? – Snake Eyes Feb 06 '18 at 11:45
  • Could you please explain what you are trying to achieve with it? Looks like you want step1, step2 and step3 to execute serially, is that right? – Siddhant Swami Feb 06 '18 at 11:45
  • @SiddhantSwami: Yes, serially, one by one. After step1 is finished, then proceed with step 2, and so on – Snake Eyes Feb 06 '18 at 11:46
  • @MagnusEriksson I disagree,'then' will not be executed untile first promise resolved.If one take 1500 ms. then "then" will be executed after 1500 ms. so chain of then will take 3 times of that which is 1500*3 – AL-zami Feb 06 '18 at 11:50
  • @AL-zami - You're correct, I misread the OP's code. – M. Eriksson Feb 06 '18 at 11:54
  • Agree with @AL-zami, it should take 1500ms each and total time should be 4500ms. Snake Eyes, can you check this on networks tab in developer tools and confirm whether you see 3 XHR requests executing one after another with a 1500ms gap. – Siddhant Swami Feb 06 '18 at 11:54

2 Answers2

1

There is nothing parallel going on in javascript. It's a concurrent language .What you wrote will be executed serially ( one after another ).It will take 1500*3 ms to finish (assuming each take 500 ms)

step1().then((data) => step2(data)).then((data) => step3(data))

To make them execute concurrently ( a.k.a parallel in js) you should do the following. All the call will be sent out to fetch data.When all of them resolves promise will go to the then-catch chain.It will take more or less 1500 ms to finish ( assuming each takes 500 ms)

Promise.all([step1(),step2(),step3()]).then().catch()
AL-zami
  • 8,902
  • 15
  • 71
  • 130
  • 2
    I think this would execute all the steps parallely, @SnakeEyes want's them to execute serially. – Siddhant Swami Feb 06 '18 at 11:51
  • If you read my post, you'll see that your first code I used in my app...No serially is done. – Snake Eyes Feb 06 '18 at 11:57
  • @SnakeEyes then will not be executed until the promise is resolved. That's the base rule. If it takes 500 ms to finish , then will not be executed until it completes and return. I am afraid I didn't get your concern – AL-zami Feb 06 '18 at 12:02
  • @AL-zami how do you explain [this](http://jsfiddle.net/saffrons/sbrk5o1g/)? – absin Feb 06 '18 at 12:09
  • @AbSin - You've got an error in you jsfiddle example, you must wrap the last console.log into function and now you just call it immideatelly. – Eugene Olisevich Feb 06 '18 at 12:19
  • @EugeneOlisevich thanks! and yes, it seems AJAX promises are *fulfilled* after response is received. – absin Feb 06 '18 at 12:26
  • @AbSin they are not called in parallel. they are both async callback, From your example it seems then is scheduled to call earlier then done. Execution is too fast to notice. Both were queued in event loop. I am pretty sure they were executed one after the other – AL-zami Feb 06 '18 at 12:32
  • @AL-zami Its not multi-threaded for sure, the question is does `then()` behave like `$.ajax().done()` does. I have updated the [fiddle](http://jsfiddle.net/saffrons/sbrk5o1g/) to check the same. It seems as though `then()` waits for the ajax call to be finished too. – absin Feb 06 '18 at 12:41
  • 1
    @AbSin done is a success handler,it is chained by fail to catch error, on the other hand then can accept two callback : success & error. That's the only distinction i know of. read here https://stackoverflow.com/questions/5436327/jquery-deferreds-and-promises-then-vs-done – AL-zami Feb 06 '18 at 12:53
  • @AbSin done and then are both being called in your fiddle upon finishing as the call is successful. Try to fail the call and see if done is called or not – AL-zami Feb 06 '18 at 12:55
  • If I try a `404` page, neither `done()` nor `then()` gets called but `fail()` gets called. [Here](http://jsfiddle.net/saffrons/sbrk5o1g/24/) – absin Feb 06 '18 at 13:03
  • add a error callback to then as second parameter. i got ajax called fail error message in my console caught by fail – AL-zami Feb 06 '18 at 13:04
  • Ah.. yes! Its [mentioned](http://api.jquery.com/deferred.then/) in the documentation and also [runs](http://jsfiddle.net/saffrons/sbrk5o1g/26/) as expected. – absin Feb 06 '18 at 15:19
0

You can use async function

An async function returns a Promise, so you can wait for the sync executions end, and then work with the returned result.

Look this code snippet

function step1() {
  return new Promise((resolve) => {
    setTimeout(function() {
      resolve(1);
    }, 1000);
  });
}

function step2() {
  return new Promise((resolve) => {
    setTimeout(function() {
      resolve(2);
    }, 1000);
  });
}

function step3() {
  return new Promise((resolve) => {
    setTimeout(function() {
      resolve(3);
    }, 1000);
  });
}

async function process() {
  var one = await step1();
  var two = await step2();
  var three = await step3();

  /*if (some error) {
    return Promise.reject('Some error!');
  }*/

  return `RESULT: ${one} - ${two} - ${three}`
}

console.log('Waiting results...');
process().then((result) => {
  console.log(result);
  console.log('DONE!');
}).catch((error) => {
  console.log(error);
});

Resource

Community
  • 1
  • 1
Ele
  • 33,468
  • 7
  • 37
  • 75