Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lost "this" reference in factory method when I tried to "ng-classify" it. #44

Open
rlrhett opened this issue Aug 24, 2015 · 1 comment

Comments

@rlrhett
Copy link

rlrhett commented Aug 24, 2015

I am sure this is a simple issue, but confusing nonetheless. I have an angular factory that I am trying to "ng-classify". The existing code looks something like this:

app.factory 'Data', [
  '$log'
  "$q'
  ($log, $q) ->
    getData1: ->
      data1 = $q.defer()
      . . .
      return data1.promise
    getData2: ->
      data2 = $q.defer()
      . . .
      return data2.promise
    getSomeComboData: ->
       comboData = $q.defer()
      $q.all(@getData1, @getData2).then (Data1, Data2) ->
      . . . 
      return ComboData.promise
    . . .
    ]

This works. No problem. Sometimes my controllers need Data1, sometimes Data2, sometimes ComboData. I can imagine other scenarios where a factory method might need to call another public method of the same factory.

This is what I did to "ng-classify" it:

class Data extends Factory
  constructor:  ($log, $q) ->
    return: {
      getData1: ->
        data1 = $q.defer()
        . . .
        return data1.promise
      getData2: ->
        data2 = $q.defer()
        . . .
        return data2.promise
      getSomeComboData: ->
        comboData = $q.defer()
        $q.all(@getData1, @getData2).then (Data1, Data2) ->
        . . . 
        return ComboData.promise
    . . .
    }

The problem is now @getdata1 and @getdata2 are undefined. Somehow the "this" reference to the factory singleton has been lost. Am I missing something?

@CaryLandholt
Copy link
Owner

I'm not exactly sure why the two would behave differently; however, I did notice a few typos.

Typos fixed

app.factory 'Data', [
  '$log'
  '$q'
  ($log, $q) ->
    getData1: ->
      data1 = $q.defer()

      return data1.promise
    getData2: ->
      data2 = $q.defer()

      return data2.promise
    getSomeComboData: ->
      comboData = $q.defer()
      $q.all(@getData1, @getData2).then (Data1, Data2) ->

      return ComboData.promise

compiles to

app.factory('Data', [
  '$log', '$q', function($log, $q) {
    return {
      getData1: function() {
        var data1;
        data1 = $q.defer();
        return data1.promise;
      },
      getData2: function() {
        var data2;
        data2 = $q.defer();
        return data2.promise;
      },
      getSomeComboData: function() {
        var comboData;
        comboData = $q.defer();
        $q.all(this.getData1, this.getData2).then(function(Data1, Data2) {});
        return ComboData.promise;
      }
    };
  }
]);

and

class Data extends Factory
  constructor:  ($log, $q) ->
    return {
      getData1: ->
        data1 = $q.defer()

        return data1.promise
      getData2: ->
        data2 = $q.defer()

        return data2.promise
      getSomeComboData: ->
        comboData = $q.defer()
        $q.all(@getData1, @getData2).then (Data1, Data2) ->

        return ComboData.promise
    }

compiles to

var Data;

Data = (function() {
  function Data($log, $q) {
    return {
      getData1: function() {
        var data1;
        data1 = $q.defer();
        return data1.promise;
      },
      getData2: function() {
        var data2;
        data2 = $q.defer();
        return data2.promise;
      },
      getSomeComboData: function() {
        var comboData;
        comboData = $q.defer();
        $q.all(this.getData1, this.getData2).then(function(Data1, Data2) {});
        return ComboData.promise;
      }
    };
  }

  return Data;

})();

angular.module('app').factory('Data', ['$log', '$q', Data]);

They are virtually identical.

Another way would be to use the Revealing Module Pattern

class Data extends Factory
  constructor:  ($log, $q) ->
    getData1 = ->
      data1 = $q.defer()

      data1.promise

    getData2 = ->
      data2 = $q.defer()

      data2.promise

    getSomeComboData = ->
      comboData = $q.defer()
      $q.all(getData1, getData2).then (Data1, Data2) ->

      ComboData.promise

    return {getData1, getData2, getSomeComboData}

compiles to

var Data;

Data = (function() {
  function Data($log, $q) {
    var getData1, getData2, getSomeComboData;
    getData1 = function() {
      var data1;
      data1 = $q.defer();
      return data1.promise;
    };
    getData2 = function() {
      var data2;
      data2 = $q.defer();
      return data2.promise;
    };
    getSomeComboData = function() {
      var comboData;
      comboData = $q.defer();
      $q.all(getData1, getData2).then(function(Data1, Data2) {});
      return ComboData.promise;
    };
    return {
      getData1: getData1,
      getData2: getData2,
      getSomeComboData: getSomeComboData
    };
  }

  return Data;

})();

angular.module('app').factory('Data', ['$log', '$q', Data]);

This way you need not worry about the this context, and it becomes evident what the exposed API is by observing the return statement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants