1

I have the following:

function functionA() {
    var myVar = functionB();
    functionC(myVar);
}

the time, functionB needs to answer, depends on user input. It may be 1s, but also 10s. So functionC always is called with an undefined value, because functionB() hasnt't finished yet. So I tried this:

function functionA() {
    var def = $.Deferred();
    var myVar = functionB();
    def.resolve();
    $.when(def).done(function () {
        functionC(myVar);
    });
}

This also doens't work. I saw this on StackOverflow: javascript function wait until another function to finish But how can it be transferred to my problem? To recap, execution of functionA needs to stop, until functionB() has answered. Thanks.

Community
  • 1
  • 1
ReyamOki
  • 83
  • 2
  • 8
  • 1
    Did you consider using the functionC() as a callback from functionB() – Trim Kadriu Jun 29 '15 at 15:42
  • @ReyamOki _"To recap, execution of functionA needs to stop, until functionB() has answered."_ "functionA" does not appear to return any value ? Can describe "needs to stop" ? , create stacksnippets, jsfiddle http://jsfiddle.net to demonstrate ? – guest271314 Jun 29 '15 at 15:48

3 Answers3

0

You can change functionB to return the deferred object, which you can then resolve within the async handler, something like this:

function functionA() {
    var deferred = functionB();
    $.when(deferred).done(functionC);
}

function functionB() {
    var deferred = $.Deferred();

    // do something async here...
    // asyncCallback() { 
    //     deferred.resolveWith(this, dataRetrieved);   
    // }

    return deferred;
}

function functionC(data) {
    console.log(data);
}
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • functionB should return user input, instead of var deferred – ReyamOki Jun 29 '15 at 16:11
  • Why's that? The logic is the same, just that now all code dependant on the callback of B is performed in the C function, instead of spread over two functions. The `data` argument of C will hold that same value. – Rory McCrossan Jun 29 '15 at 16:23
  • I dont't understand the purpose of returning deferred in functionB. $.when(deferred) will never fire. I also don't get why functionC expects a data parameter, but you call it in functionA without a paramter. FunctionB should return user input, to use it in functionA. I just don't know, how to pause execution of funtionB until the input has finished. Something like deferred.resolve(); return userInput; or just return userInput(); doesn't work, because the returned value is undefined. – ReyamOki Jun 29 '15 at 17:14
  • `$.when(deferred) will never fire` Yes it will, when it's called via `resolveWith` from functionB. To help clear your confusion, I would suggest you research async patterns in JavaScript. – Rory McCrossan Jun 29 '15 at 18:20
  • Ok, so I tried your approach. But look at this fiddle: https://jsfiddle.net/4DAfn/261/ deferred variable in functionA seems always to be done. Thus functionC is immediately called. Where is the problem? – ReyamOki Jun 30 '15 at 08:08
  • There's a lot of issues there. Your `deferred` variable is not a `$.Deferred` object, also, the `done` is being assigned the result of `console.log`, not an anonymous function. If you use it properly it works: https://jsfiddle.net/4DAfn/263/ – Rory McCrossan Jun 30 '15 at 08:13
  • Yes, but how can I then say. var deferred = functionB();? In the next line, deferred will be done, before functionB has been called.Sorry for my stupidity :) – ReyamOki Jun 30 '15 at 08:23
  • But deferred won't be done until `resolve()` (or `resolveWith()`) is called by the callback function of your asynchronous code - that's what the `setTimeout` is emulating in my fiddle example – Rory McCrossan Jun 30 '15 at 08:26
  • Ok, I got it. In fiddle your approach works perfectly now. But in my code it doesn't. I do something like this: var deferred = (helper.getInput()); $.when(deferred).done(functionC); function functionC(data) {image.src = data;} $.when(deferred).done always fires immediately. An idea why? In helper.getInput() I do, what you did in functionB. – ReyamOki Jun 30 '15 at 08:44
  • At this point it may be worth starting a new question, with that code as the opener. – Rory McCrossan Jun 30 '15 at 08:52
  • No problem, glad to help. – Rory McCrossan Jun 30 '15 at 09:00
0

Putting your example in a simple object, you can do the following:

var myObject = {
    myProp: null,
    functionA: function () {
        this.functionB();
        var self = this;
        var i = setInterval(function () {
            if (self.myProp) {
                clearInterval(i);
                self.functionC();
            }
        }, 100);
    },
    functionB: function () {
        // ...
        this.myProp = 'user input';
    },
    functionC: function () {
        // ...
    }
};
myObject.functionA();

The script will check every 0.1s if myProp is set. If so, the interval is cleared and functionC is called.

No jQuery needed in this case.

viarnes
  • 2,018
  • 2
  • 19
  • 31
-1

You can pass functionC as a parameter to your functionB as mention here.

function functionA() {
   var myVar = functionB(callback);
   functionC(myVar);
}

function functionB(callback) {
   // does something ...
   if(callback && typeof(callback) === "function") {
      callback();
   }
}
Community
  • 1
  • 1
Marco
  • 175
  • 2
  • 8