0

I have a long running function A(). And my function B(){} can be called anytime.

Note function B doesn't have to be called after A. But if it is called and if A is running, then A must be finished. And then run B.

I thought about promise.then(), but B may not necessarily be called after A. So it is not much useful in this situation.

How to 'queue' B to ensure the logic?

Tianyun Ling
  • 1,045
  • 1
  • 9
  • 24
  • What makes you think that B will start executing before A finishes? What is your environment? You may want to read something like this: http://stackoverflow.com/questions/2734025/is-javascript-guaranteed-to-be-single-threaded – Vladimir M May 10 '17 at 20:13
  • are A and B synchronous or asynchronous? If they are both synchronous you don't need to do anything, A will halt the execution of B until it's finished. – Brian Glaz May 10 '17 at 20:14
  • Both A and B is async. – Tianyun Ling May 10 '17 at 20:15
  • 1
    Set a flag. Call A. Use a .then. If the flag is set, place B in a queue array, else call B. In the .then clear the flag, then call any functions in the queue array. – Travis J May 10 '17 at 20:15

3 Answers3

3

Don't use flags! They are completely unnecessary.

Also don't do anything special in A() or B(). Just write them as you would normally to perform their duties.

Just implement a queue in the form of a dynamically updated promise chain.

var q_ = Promise.resolve();

function queue(fn) {
    q_ = q_.then(fn);
    return q_;
}

Now you can queue A and B, or any other function, as follows :

queue(A);
queue(B);
queue(someOtherFunction);

Or, if you need to pass parameters :

queue(A.bind(null, 'a', 'b', 'c'));
queue(B.bind(null, 'x', 'y', 'z'));
queue(someOtherFunction.bind(null, 1, 2, 3));

As a bonus,

  • A() and B() (and other functions) remain available to be called directly (unqueued).
  • you needn't worry whether functions passed to queue() are synchronous or asynchronous. It will work with either.

DEMO

Roamer-1888
  • 19,138
  • 5
  • 33
  • 44
1

Do something like this: Define a variable var inQueue = 0; When A starts, set a variable inQueue = 1, when it finishes, set it to inQueue = 0. Now place a check like

if(!inQueue) B();

This will ensure B won't interrupt A.

gaganshera
  • 2,629
  • 1
  • 14
  • 21
1

Use a variable that is true when A is running and is set to false at the end of A. Check that within B. If it is running, have it wait a second and call B again.

var isARunning

A() {
  isARunning = true
  //do the things
  isARunning = false
}

B() {
  if (isARunning) {
   setTimeout(() => { B() }, 1000);
  }
  else {
    // do more things
  }
}
larz
  • 5,724
  • 2
  • 11
  • 20