guest
guest

Reputation: 2224

using function caller names in method chaining

I have the following Pet and cat inherits from Pet, as follows:

function Pet(){};

Pet.prototype.run = function takeoff(cb, sec) {
 setTimeout(function() {
   cb();
   console.log('Run');
 }, sec);
};
Pet.prototype.bark = function bark(cb, sec) {
 setTimeout(function() {
   cb();
   console.log('bark');
 }, sec);
};
Pet.prototype.comeback = function comeback(cb, sec) {
 setTimeout(function() {
   cb();
   console.log('Comeback');
 }, sec);
};

var cat = new Pet();
cat.prototype = Object.create(Pet);

cat.prototype.run = function(){
    var that = this;

    that.run = Pet.prototype.run.call(that);
    return that;
}

cat.prototype.bark = function(){
    this.bark = Pet.prototype.bark.call(this);
    return this;
}

cat.prototype.comeback = function(){
    this.comeback = Pet.prototype.comeback.call(this);
    return this;
}


console.log(cat);
cat.run().bark().return();

In this situation, the cat and Pet have the same function names. The only difference is return this is added to cat methods to make method chaining possible in cat but not Pet. However, note that I have to write the name of the function every time and set the same name to its parent's prototype. Is it possible to generalize this so that any method I specify for Pet will be duplicated in cat but yet I don't have to specify the method for cat every time?

Upvotes: 0

Views: 89

Answers (2)

TOAOGG
TOAOGG

Reputation: 392

After a discussion with guest I came up with a solution that extends each function to use a promise. The code will be executed in order and the object will be chained.

function Pet(){};

Pet.prototype.run = function run(callback) {
 setTimeout(function() {
   callback()
   console.log('Run');
 }, 1000);
};
Pet.prototype.bark = function bark(callback) {
 setTimeout(function() {
   callback()
   console.log('Bark');
 }, 500);
};
Pet.prototype.comeBack = function comeBack(callback) {
 setTimeout(function() {
   callback()
   console.log('Comeback');
 }, 750);
};

// DON'T MODIFY ANYTHING ABOVE HERE

// START ADD YOUR CODE HERE

function createChainableFunction(fun) {
      var that = this;
      return function() {
          if(!that.promise) {
            that.promise = new Promise(function(resolve, reject) {
              fun.call(that, resolve);
            });
          }
          else {
            that.promise.then(function() {
                that.promise = new Promise(function(resolve) {
                  fun.call(that, resolve);
                });
            });
          }


          return this;
      }
}

function isFunction(functionToCheck) {
   var getType = {};
   return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}

function createChainable(object) {
   var chainable = {
   'promise': null
   };
   chainable.prototype = Object.getPrototypeOf(object);
   for(var prop in object) {
      if(isFunction(object[prop])) {
         chainable[prop] = createChainableFunction.call(chainable.prototype, object[prop], prop);
      }
   }

   return chainable;
}

var cat = createChainable(new Pet());

cat.run().bark().comeBack();

Upvotes: 1

Rajesh
Rajesh

Reputation: 24925

You can add a property in child classes and based on this value, you can return this.

Sample

// Parent Class
function Pet() {
  this.sec = 1000
};

Pet.prototype.run = function takeoff(cb, sec) {
  setTimeout(function() {
    //cb();
    console.log('Run');
  }, sec || this.sec);
  if (this.animalName) return this;
};
Pet.prototype.bark = function bark(cb, sec) {
  setTimeout(function() {
    //cb();
    console.log('bark');
  }, sec || this.sec);
  if (this.animalName) return this;
};
Pet.prototype.comeback = function comeback(cb, sec) {
  setTimeout(function() {
    //cb();
    console.log('Comeback');
  }, sec || this.sec);
  if (this.animalName) return this;
};

// Child class
var Cat = function() {
  this.animalName = 'Cat'
}

// Linking of classes
Cat.prototype = new Pet();

// object of child class
var cat = new Cat();
cat.run().bark().comeback()

var pet = new Pet();
try {
  // Chaining not allowed.
  pet.run().bark().comeback()
} catch (ex) {
  console.log(ex.message)
}

Upvotes: 1

Related Questions