0

I'm making an application using ES6, AngularJS and babel-loader 7.1.4, Webpack 3 . Everything worked fine until I created a service file:

This is my service:

'use strict';

module.exports = (ngModule) => {

    ngModule.service('$ui', () => {


        //#region Methods

        /*
        * Trigger windows resize function.
        * */
        this.reloadWindowSize = () => {
            $(window).resize();
        };

        //#endregion
    });
};

After transpilling source code from ES6 to ES2015, my service became:

module.exports = function (ngModule) {

    ngModule.service('$ui', function () {

        //#region Methods

        /*
        * Trigger windows resize function.
        * */
        _this.reloadWindowSize = function () {
            $(window).resize();
        };

        //#endregion
    });
};

As you see, this now becomes _this, therefore, I cannot execute the function in service file.

This is my babel configuration

{
    test: /\.js$/,
    exclude: /(node_modules|bower_components)/,
    use: {
        loader: 'babel-loader',
        options: {
            presets: [['env', { "modules": false }]]
        }
    }
}

What wrong am I doing ?

Can anyone help me please?

Thank you,

Redplane
  • 2,971
  • 4
  • 30
  • 59

2 Answers2

3

Arrow functions aren't just shortcuts for regular functions.

As the reference states,

Two factors influenced the introduction of arrow functions: shorter functions and non-binding of this.

Since source code contains several nested arrow functions, this is retrieved from top-level scope through _this variable, which is undefined, because it's module scope, and strict mode is enabled.

It's semantically incorrect to use arrow functions for service services, because they are instantiated with new and use this as service instance, while arrows cannot be newed and don't have own this.

It should be:

ngModule.service('$ui', function () {
    //#region Methods

    /*
    * Trigger windows resize function.
    * */
    this.reloadWindowSize = () => {
        $(window).resize();
    };

    //#endregion
});
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
0

After reading this topic. I have found the answer.

I changed my service implementation from :

'use strict';

module.exports = (ngModule) => {

    ngModule.service('$ui', () => {


        //#region Methods

        /*
        * Trigger windows resize function.
        * */
        this.reloadWindowSize = () => {
            $(window).resize();
        };

        //#endregion
    });
};

To this:

module.exports = (ngModule) => {

    ngModule.service('$ui', () => {

        return {

            //#region Methods

            /*
            * Reload window size.
            * */
            reloadWindowSize: () => {
                $(window).resize();
            }

            //#endregion
        }
    });
};

Within service declaration, I return a set of functions and it worked.

Just want to let anyone know about this. It took me a night to find the answer.

Redplane
  • 2,971
  • 4
  • 30
  • 59
  • `ngModule.service('$ui', () => {` - this is what `factory` is for. And you can't refer to service instances this way. – Estus Flask May 07 '18 at 16:13
  • Can you explain more ? For now, I can inject the $ui service to my controller. – Redplane May 07 '18 at 16:16
  • If you need to access service instance inside service method, you won't be able to do that. – Estus Flask May 07 '18 at 16:18
  • As I understand correctly what you want to say that I can't inject another service instance into $ui service . If so, I already tried and it worked. Here is my repo : https://github.com/redplane/ng-structure.git (master branch) – Redplane May 08 '18 at 02:12