-1

I'm trying to create a bounce effect on an image after an synchronous AND an asynchronous call but can't figure out how to do it. The problem I'm having now is that I sometimes get both the bounce effect and afterwards isExecuted becomes true because the asynchronous event takes some time.

My code should work like this:

Iterate over each object in myEnum and execute the following

  • if myCondition1 is equal too myCondition2 set isExecuted = true
  • if above is not true, call an asynchronous method which evaluates some stuff, if it's true it will set isExecuted = true.
  • wait for all above is finished, then if isExecuted still is false, bounce the image.

Here's the code:

var isExecuted = false;

myEnum.each() 
{
    if (myCondition1 == myCondition2) { //Synchronous 
        isExecuted = true;
        return false; //stop the iteration
    }   
    else {
        MyAsyncFunction(myCondition2, function(isTrue) { // Asynchronous
            if (isTrue) {
                isExecuted = true;
                return false; //stop the iteration
            }                   
        });
    }
});

// Execute this ONLY when above code is finished executing
if (isExecuted == false) {
    BounceImage();
}

Please note that the async function is not always executed but the bounce check must always be executed if isExecuted is true.

dadde
  • 649
  • 1
  • 11
  • 24
  • 1
    Where is the `index` in `$("a#" + index + " img")` coming from? The generic answer to this is: Use promises and `Promise.all`. – Felix Kling Mar 08 '17 at 17:18
  • callbacks can help but I don't know about writing them in javascript – Madhusoodan P Mar 08 '17 at 17:18
  • Also, what is `myVar`? – Tomalak Mar 08 '17 at 17:18
  • @FelixKling It's coming from `myEnum.each(function(index)` and it's not really relevant to the question... – dadde Mar 08 '17 at 17:19
  • 1
    @MadhusoodanP Why comment at all when you wouldn't know how to help? – Tomalak Mar 08 '17 at 17:19
  • @dadde: But the `if` statement is outside the `myEnum.each()` callback. – Felix Kling Mar 08 '17 at 17:19
  • @Tomalak it can be anything... if "a" == "a" then true else false...? Let me update the code – dadde Mar 08 '17 at 17:21
  • Now the code is even more wrong.... Please post a [mcve]. *"it's not really relevant to the question..."* It's relevant in so far as it seems you want to execute `$("a#" + index + " img").stop().effect("bounce", ...)` after all async requests are done. Or is that not correct? If not, then where is the problem? Put the `if` statement inside the callback, or inside a function that you call from the callback. – Felix Kling Mar 08 '17 at 17:24
  • Possible duplicate of [How do I return the response from an asynchronous call?](http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – CBroe Mar 08 '17 at 17:29
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise – Jared Smith Mar 08 '17 at 17:30
  • @FelixKling How about now (edited the question some more)? If I put the `if` inside the callback it will only bounce when the async event is true but I want the bounce effect also if only the synchronous event is executed (notice the `return false` that breaks the loops). – dadde Mar 08 '17 at 17:32
  • The `return false;` inside the asynchronous callback has no effect on the `.each` loop. I think you have to approach this entirely differently. – Felix Kling Mar 08 '17 at 17:34
  • @FelixKling Oh yes you are right thanks for pointing that out. But what about the bounce? – dadde Mar 08 '17 at 17:39
  • I'd refactor everything so that you can do something like `process(myEnum).then(isExecuted => { if (!isExecuted) { BounceImage(); }});`, where `process` somehow iterates over your array, performs the async calls and comparisons and returns a promise. – Felix Kling Mar 08 '17 at 17:41
  • @FelixKling Good! Can you elaborate with an example? I'm rather new to javascripting... – dadde Mar 08 '17 at 17:42

2 Answers2

1

This whole setup won't work as you want because you cannot stop the iteration from the asynchronous callback. Instead you have to process the array (or whatever myEnum is) asynchronously and do something afterwards. I highly recommend to learn about promises.

function process(array, cb) {
  var i = 0;
  
  function p(v) {
    return new Promise((resolve, reject) => {
      try {
        // call the callback, passing in the current value and 
        // a callback to control execution
        cb(v, function next(stop, result) {
          if (stop) {
            // if stop = true, abort the iteration and resolve the passed in value
            resolve(result);
          } else if (i < array.length) {
            // else if there are more elements left, process them
            resolve(p(array[i++]));
          } else {    // else resolve to the passed in value
            resolve(result);
          }
        });
      } catch(e) {
        reject(e);
      }
    });
  }
  
  // start with the first element
  return p(array[0]);
}

process([1,2,3], function(v, next) {
  if (v == 2) {
    return next(true, v);
  }
  next();
}).then(result => console.log(result));

Applied to your code it would look something like

process(myEnum, function(v, next) {
  if (myCondition1 == myCondition2) {
    return next(true, true);
  } else {
    MyAsyncFunction(myCondition2, function(isTrue) {
      if (isTrue) {
        return next(true, true);
      }
      next();                 
    });
  }
}).then(function(isExecuted) {
  if (!isExecuted) {
    BounceImage();
  }
});

Of course you can also use an existing library that allows you to do this. There a many different (potentially more elegant) ways to achieve this.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
0

Instead, use callbacks:

function asyncFunction (a, b, c, callback) {
  ...
  callback();
}

asyncFunction(1, 2, 3, function () {
  doSomethingOnceDone();
});

This is a very common practice. It's how most async Chrome APIS do it, just to name one thing.

Domino
  • 6,314
  • 1
  • 32
  • 58