4

I have a function (f1) which I want to get called only after two ajax calls (say a1 and a2) are done. a2 should be called only after a1 is done. Following is the sequence of operation =

$.when(a1 and a2) {
   f1
}

I tried the following code snippet -

$.when(a1a2()).done(function(){
  f1();
}

var a1a2 = function(){
  return $.when(a1()).done(function() {
    if (<check for a few variables a1 sets>) {
      // another ajax call for which f1 should wait
      return a2();
    } else {
      // random function for which f1 shouldn't wait
      f2();
    }
  });
}

In the above code, f1 is waiting for a1 to finish but it is not waiting for a2 to finish.

I tried the following code snippet as well (but this also just waits for a1 to finish) -

var a1a2 = function(){
  var retVal = new Promise(function(){
    a1().then(function(){
      if (<check for a few variables a1 sets>) {
        return a2();
      } else {
        // random function for which f1 shouldn't wait
        f2();
      }
    });
  });
}

I have looked at other similar questions but an not able to devise a solution. Can someone please help?

user2851669
  • 341
  • 1
  • 4
  • 18
  • 1
    `new Promise(function(){` that's NOT how you create a Promise - that promise will remain pending forever – Jaromanda X May 28 '19 at 00:04
  • 2
    Possible duplicate of [Resolve promises one after another (i.e. in sequence)?](https://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence) – Heretic Monkey May 28 '19 at 00:56

4 Answers4

2

Call a1 to get its Promise, then call Promise.all on a1 and a1 chained with a2:

const a1Prom = a1();
Promise.all([
  a1Prom,
  a1Prom.then(a2)
])
  .then(f1);

console.log('script start');

const delay = ms => new Promise(res => setTimeout(res, ms));
const a1 = () => delay(1000).then(() => console.log('a1 done'));
const a2 = () => {
  console.log('a2 starting');
  return delay(1000).then(() => console.log('a2 done'));
};

const f1 = () => console.log('f1 starting');



const a1Prom = a1();
Promise.all([
  a1Prom,
  a1Prom.then(a2)
])
  .then(f1);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • This didn't work for me, it isn't waiting for a2's execution. a2 is not returning any promise – user2851669 May 28 '19 at 09:58
  • 1
    Yeah, you need to make sure `a2` returns a Promise in order to use it with asynchronous code like this (but you didn't post any of the `a2` code). If you do that, press "Run code snippet", you'll see that it runs as desired – CertainPerformance May 28 '19 at 10:02
  • Is there any way I can either return a promise or null (in case I don't want to wait) – user2851669 May 28 '19 at 18:46
2

First of all, your Promise code is faulty, because you're not creating a Promise correctly

new Promise(function(resolve, reject) {
    // in here you call resolve or reject otherwise Promise is forever pending
});

However, since a1 returns a Promise (as do all the functions, I'm assuming) you don't need to create a promise

So, your code would be

a1()
.then(function() {
    if (somecondition == true) {
        return a2();
    } else {
        f2(); // since there's no return here, there's no "wait" for the promise f2 returns
    }
})
.then(function() {
    return f1();
})

To illustrate the above, here's your code once with condition true, and then with condition false

Take note of the "time stamps" for the console output

// dummy code to set up some promises
const dummy = (x, d=1000) => {
    console.log(performance.now(), 'start', x);
    return new Promise(resolve => setTimeout(() => {
        console.log(performance.now(), 'end', x);
        resolve(x);
    }, d));
};

const a1 = () => dummy('a1');
const a2 = () => dummy('a2');
const f1 = () => dummy('f1');
const f2 = () => dummy('f2', 3000);

// end dummy code

console.log('wait for a2');
a1()
.then(function() {
    if (true) {
        return a2();
    } else {
        // random function for which f1 shouldn't wait
        f2();
    }
})
.then(function() {
    return f1();
})
.then(() => {
    console.log('dont wait for f2');
    a1()
    .then(function() {
        if (false) {
            return a2();
        } else {
            // random function for which f1 shouldn't wait
            f2();
        }
    })
    .then(function() {
        f1();
    });
});

However! If f2 is a function that has no asynchrony then there is no way * to prevent f1 from being called after f2 finish - because that's how javascript works

* - I guess you could put it in a setTimeout, then f2 would execute after f1 begins (again, assuming f1 has some asynchrony, otherwise f2 would begin after f1 ends)

Community
  • 1
  • 1
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
0

I'm not familiar with the when/done syntax, but this is a correction for your second snippet. A big hint I would give is that using new Promise is 90% of the time a bad idea.

var a1a2 = function(){
  var retVal = a1().then(function(){
    if (<check for a few variables a1 sets>) {
      return a2();
    } else {
      // random function for which f1 shouldn't wait
      f2();
    }
  });
});
Evert
  • 93,428
  • 18
  • 118
  • 189
0
function a1() {
  return new Promise(resolve => { 
     resolve();
  });
}

function a2() {
  return new Promise(resolve => {
    resolve();
  });
}

function f1() {
  // this runs when the a1 and a2 is resolved.
}

// this is the call method. there are so many approach in your question first is chaining of promise.
function CallMethod(){
   a1().then(function () { // you can optionally pass data here via the resolve in the promise
      return a2();
   }).then(function () { // same here you can pass optional data here.
      // here the a1 and a2 is resolved you can call the f1() now.
      f1();
   });
}
// second one is called Promise.all()
function CallMethod() {
  Promise.all([a1(), a2()]).then(data => { // this is the optional data passed in the resolve base on the index of the function promises. 
     var firstResolve = data[0]; // resolved data of a1();
     var secondResolve = data[1]; // resolved data of a2();
  })
}