Подтвердить что ты не робот

Как я могу определить услугу AngularJS с помощью класса TypeScript, который не загрязняет глобальную область?

Я использую AngularJS и TypeScript. Я хочу реализовать службу AngularJS с помощью класса Typescript, например:

class HelloService {
    public getWelcomeMessage():String {
        return "Hello";
    }
}

angular.module('app.services.helloService', []).factory('helloService', () => {
    return new HelloService();
});

Скомпилируется следующий код javascript:

var HelloService = (function () {
    function HelloService() {
    }
    HelloService.prototype.getWelcomeMessage = function () {
        return "Hello";
    };
    return HelloService;
})();

angular.module('app.services.helloService', []).factory('helloService', function () {
    return new HelloService();
});

Это загрязняет глобальное пространство имен переменной HelloService, чего я, очевидно, не хочу. (Используя консоль Chrome, я подтвердил, что HelloService был объектом.) Как я могу решить эту проблему или избежать этой проблемы?

Я пробовал очевидное:

angular.module('app.services.helloService', []).factory('helloService', function () {
    class HelloService { ...} 
    return new HelloService();
});

но это дает мне ошибку компиляции ( "Непредвиденный токен, выражение" ожидается ".).

Одним из возможных решений, о которых я могу думать, является использование Typescript импорта и экспорта как-то, что, в свою очередь, будет использовать RequireJS. Вероятно, это приведет к завершению HelloService в функции определения, что позволит избежать загрязнения глобальной области с помощью HelloService. Тем не менее, я не хочу использовать RequireJS в своем приложении AngularJS, так как я думаю, что AngularJS достаточно хорош для моего использования, и это добавляет сложности.

Итак, мой вопрос: как я могу определить услугу AngularJS с помощью класса Typescript, который не загрязняет глобальную область?

4b9b3361

Ответ 1

Я должен предоставить то, что я на самом деле закончил:

module MyModule {
    export class HelloService {
        public getWelcomeMessage():String {
            return "Hello";
        }
    }

    angular.module('app.services.helloService', []).factory('helloService', () => {
        return new HelloService();
    });
}

Таким образом, я могу использовать

return new HelloService();

вместо

return new MyModule.HelloService();

Ответ 2

2016-05-06: Новый пример с использованием модулей в стиле ES6

Статический массив и конструктор $inject остаются неизменными из предыдущего примера.

Единственное изменение - разбить классы на несколько файлов и использовать модули ES6 для определения определений классов.

/lib/HelloService.ts:

export class HelloService {
    public getWelcomeMessage():String {
        return "Hello from HelloService";
    }
}

/lib/AnotherService.ts:

import {HelloService} from './HelloService';

/**
 * Service that depends on HelloService.
 */
export class AnotherService {

    // Define `HelloService` as a dependency.
    static $inject = ['HelloService'];
    constructor(
        // Add the parameter and type definition.
        public HelloService: HelloService
    ){}

    public getWelcomeMessage():String {
        // Access the service as: `this.HelloService`
        // Enjoy auto-completion and type safety :)
        var helloMsg = this.HelloService.getWelcomeMessage();
        return "Welcome from AnotherService, " + helloMsg;
    }
}

/index.ts:

// Using the services.
import {HelloService} from './lib/HelloService';
import {AnotherService} from './lib/AnotherService';

angular.module('HelloApp', [])
    .service('HelloService', HelloService)
    .service('AnotherService', AnotherService)
    .run(['AnotherService', function(AnotherService: AnotherService){
        console.log(AnotherService.getWelcomeMessage());
    }]);

Предыдущий ответ: использование пространств имен

Создание из ответа Стив Фентона:

Чтобы разрешить инъекцию зависимостей, добавьте в свой класс статический массив $inject.

См. Angular $инжекторная документация о том, как работает массив $inject.

Зависимости будут вставляться в ваш конструктор в порядке, заданном массивом (и заставляет его работать с минимизацией).

Пример инъекции зависимостей:

namespace MyModule {
    /**
     * Angular Service
     */
    export class HelloService {
        public getWelcomeMessage():String {
            return "Hello from HelloService";
        }
    }

    /**
     * Service that depends on HelloService.
     */
    export class AnotherService {

        // Define `HelloService` as a dependency.
        static $inject = ['HelloService'];
        constructor(
            // Add the parameter and type definition.
            public HelloService: MyModule.HelloService
        ){}

        public getWelcomeMessage():String {
            // Access the service as: `this.HelloService`
            // Enjoy auto-completion and type safety :)
            var helloMsg = this.HelloService.getWelcomeMessage();
            return "Welcome from AnotherService, " + helloMsg;
        }
    }
}


// Using the services.
angular.module('app.services.helloService', [])
    .service('HelloService', MyModule.HelloService)
    .service('AnotherService', MyModule.AnotherService)
    .run(['AnotherService', function(AnotherService: MyModule.AnotherService){
        console.log(AnotherService.getWelcomeMessage());
    }]);

Ответ 3

У меня есть два решения, первый дает вам синтаксис на основе классов, второй ничего не оставляет в глобальном масштабе...

Вы можете слегка скомпрометировать, добавив только один дескриптор в глобальную область (это действительно применимо, если у вас есть несколько классов, которые вы хотите избежать в глобальной области, так как в настоящее время у вас есть только один класс).

Следующий код оставляет только модуль в глобальной области.

module MyModule {
    export class HelloService {
        public getWelcomeMessage():String {
            return "Hello";
        }
    }

    export class AnotherService {
        public getWelcomeMessage():String {
            return "Hello";
        }
    }

}

angular.module('app.services.helloService', []).factory('helloService', () => {
    return new MyModule.HelloService();
});

angular.module('app.services.anotherService', []).factory('anotherService', () => {
    return new MyModule.AnotherService();
});

В качестве альтернативы, чтобы не оставить ни одной вещи в глобальной области, вы могли бы избежать синтаксиса класса и использовать "простой старый JavaScript":

angular.module('app.services.helloService', []).factory('helloService', () => {
    var HelloService = (function () {
        function HelloService() {
        }
        HelloService.prototype.getWelcomeMessage = function () {
            return "Hello";
        };
        return HelloService;
    })();

    return new HelloService();
});

Ответ 4

Это метод, которым я следую:

module HelperServices {
    export class helloService {
       sayHelloWorld: () => string;
        constructor() {
            this.sayHelloWorld = () => {
                return "Hello World";
            }
        }
    }
}

Проще всего это.