Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular service with ES6 class and Babel

I'm trying to use an ES6 class as an Angular service but when it's instantiated, the methods do not have access to the constructor variables.

class dataWrapperService {

    constructor($q, $log) {
        this.$q = $q;
        this.$log = $log;
    }

    data() {
        console.log(this.$q);
    }
}

dataWrapperService.$inject = ['$q', '$log'];

app.service('dataWrapper', dataWrapperService);

Once the service gets injected by Angular and I call the data method on it, the method fails to have access to the constructor values.

// calling the data method results in an error
dataWrapper.data();   //TypeError: Cannot read property '$q' of undefined

//  console.log output of dataWrapper:
Object
  $log: Object
  $q: Q(resolver)
  __proto__: smDataWrapperService
    constructor: smDataWrapperService($q, $log)
    data: data()
    __proto__: Object

BUT...

I can new the dataWrapperService manually and that works just fine.

var dataWrapper = new smDataWrapperService("hello", "sir");
dataWrapper.data();   // "hello"

What am I missing here?

UPDATE:


This seems to be happening only in promise callbacks:

I usually pass functions to then / catch like this:

$http.get('whatever').then(dataWrapper.data);

But only the following will work:

$http.get('whatever').then((response) => smDataWrapper.data(response))
like image 379
Justin Avatar asked Sep 03 '15 19:09

Justin


2 Answers

Angular needs a function at app.factory('dataWrapper', dataWrapperService); and not a class.

You could add a static factory method to your class and add that to app.factory. (see update below code snippet)

The code like this should work:

class dataWrapperService {

    constructor($q, $log) {
        this.$q = $q;
        this.$log = $log;
    }

    data() {
        console.log(this.$q);
    }

    static dataWrapperFactory($q, $log) {
        dataWrapperService.instance = new dataWrapperService($q, $log);
        return dataWrapperService.instance;
    }
}

dataWrapperService.$inject = ['$q', '$log'];

app.factory('dataWrapper', dataWrapperService.dataWrapperFactory);

Update

So as mentioned in the comments your code should work because an ES6 class is a constructor function and that's what angular.service is expecting.

I'll check later if I can see any other issue with your code.

like image 144
AWolf Avatar answered Oct 13 '22 23:10

AWolf


I know this is late, but maybe somebody will stumble upon this issue like me today with similar problems, so...

Actually, it's not about promises. When you do this:

let function1 = () => {}
let function2 = function1

actually, this object is different for the functions. Therefore, when you try .then(function1), actually function1 is being copied to the param successCallback and it's this is changed.

But when you use .then(() => function1()), successCallback receives your lambda, and the actual this of function1 is not lost.

So if you do not know, what you do never assign a function to a function in javascript, use lambdas instead

like image 23
SMSk Avatar answered Oct 13 '22 23:10

SMSk