0

Previously I had

 MyClass.prototype.method1 = function(data1) {
    return this.data111.push(data1);
  };

 MyClass.prototype.method2 = function(i) {
    var data = this.method1(i);
    if (data.condition1 != null) {
      data.onEvent1(this);
    }
    return $(data.element).someMethod123("data123");
  };

 MyClass.prototype.method3 = function() {
    var data1 = this.method1(this._data1);
    return this.someMethod123(step.data1);
  };

MyClass.prototype.ended = function() {
    return !!this.getState("end");
  };


MyClass.prototype.getState = function(key) {
    var value = $.cookie(key);
    this._options.afterGetState(key, value);
    return value;
  };

How do I make async using callback functions? I guess it should be so:

 MyClass.prototype.method1 = function(data1, callback) {
    if(callback){
      callback(this.data111.push(data1));
    }
    else{
      return this.data111.push(data1);
   }
  };

 MyClass.prototype.method2 = function(i, callback) {

    var data = this.method1(i);
    if (data.condition1 != null) {
      data.onEvent1(this);
    }
    if(callback){
      callback($(data.element).someMethod123("data123"));
    }
    else{
     return $(data.element).someMethod123("data123");
    }
  };

 MyClass.prototype.method3 = function(callback) {
    var data1 = this.method1(this._data1);
     if(callback){
      callback(this.someMethod123(step.data1));
    }
    else{
       return this.someMethod123(step.data1);
    }
  };

MyClass.prototype.ended = function(callback) {
    if(callback){
       callback(!!this.getState("end", /*what should be here and what should it does?*/));
    }
  };


  MyClass.prototype.getState = function(key, callback) { 
    var oldThis = this;
    setTimeout(function(){ 
                    value = $.cookie(key);
                    callback(value, oldThis); 
                    oldThis._options.afterGetState(key, value);
                  },
              0);
  };

I definitely have missed something because I never used async functions in javascript before. So it that?

And, as I understood, to make a functions async, I basically should add one more parameter as a callback function and get rid of return, should not I?

Alan Coromano
  • 24,958
  • 53
  • 135
  • 205

2 Answers2

1

Just pass on the callback:

MyClass.prototype.ended = function(callback) {
    this.getState("end", callback);
};

You should do this in your other functions too and I'd suggest to stick to one interface. I.e. either return the value directly (if possible) or use callbacks.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • For instance, if I call somewhere `if(this.ended(/* what should I do here?*/)) { .... }`, how do I handle it? – Alan Coromano Jan 29 '13 at 11:37
  • 1
    Since `.ended` does not return a value, you would call the function this `this.ended(function(result) { /* do something with result*/ });`. The way you write your code changes when you use callbacks. – Felix Kling Jan 29 '13 at 11:40
  • it does return the value, look at my first example. – Alan Coromano Jan 29 '13 at 11:45
  • 3
    Yes, if you don't use callbacks it does. But not when you use callbacks... did you even see my code? ;) You cannot return a value form a function which calls a function that needs a callback and is async. If you use callbacks, you have to use them all the way through. – Felix Kling Jan 29 '13 at 11:48
  • Can I return value from this code: `setTimeout(function(){ value = $.cookie(key); callback(value, oldThis); return oldThis._options.afterGetState(key, value); }, 0);` ? – Alan Coromano Jan 29 '13 at 14:33
  • @Alan: No... the value is returned to whatever calls your callback, which is not your code. The return value is just lost. Maybe you find this question/answer helpful as well: http://stackoverflow.com/q/14220321/218196. – Felix Kling Jan 29 '13 at 15:15
  • did ask that question and answer yourself? – Alan Coromano Jan 29 '13 at 15:43
  • Yes, because it's such a common question that needed an extensive explanation. – Felix Kling Jan 29 '13 at 15:44
1

Only those methods that do asynchronous tasks need callback style. There is no reason to use it for method1, method2 and method3.

getState now is the actual asynchronous method. Using ajax/setTimeout/whatever is quite obvious in here. Yet, I can spot one mistake: The callback call should always be the last statement, just as you won't do anything after a return statement. Even though you can, better call back after setting the internal options object:

                …
                oldThis._options.afterGetState(key, value);
                callback(value, oldThis);

Now, the ended method. Since it uses the async getState, it will become asynchronous itself and you need to use callback style (notice that getState() will not return the value). So you will call getState, and when that calls back you will transform the result and pass it to your own callback:

MyClass.prototype.ended = function(callback) {
    this.getState("end", function ownCallback(state) {
        var result = !!state; // or whatever you need to do
        callback(result);
    });
};
// and if you don't need to do anything with the result, you can leave out ownCallback:
MyClass.prototype.ended = function(callback) {
    this.getState("end", callback);
};
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Great explanation! why is it better to raise the "event" `afterGetState` before callback? I won't work properly because it will be raised before the state has been gotten. – Alan Coromano Jan 29 '13 at 16:13
  • <> Why did you add `callback` parameter for `MyClass.prototype.ended = function(callback)` then? I only want to do `return !!this.getState("end");` there, how can I do that? – Alan Coromano Jan 29 '13 at 16:26
  • @AlanDert: Oh, it's an event? Then it might be OK. However, the callback function is quite like an event handler, and handlers should in general not depend on each other. – Bergi Jan 29 '13 at 16:46
  • @AlanDert: Why `ended` has a callback? Because it is asynchronous - it uses the async `getState`! – Bergi Jan 29 '13 at 16:47
  • It's clear now. So what if I want to call `this.ended(/*....*/)`, what should put there as a callback parameter? – Alan Coromano Jan 29 '13 at 17:42