【问题标题】:Angular service with ES6 class and Babel带有 ES6 类和 Babel 的 Angular 服务
【发布时间】:2015-09-03 19:46:10
【问题描述】:

我正在尝试将 ES6 类用作 Angular 服务,但是当它被实例化时,这些方法无法访问构造函数变量。

class dataWrapperService {

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

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

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

app.service('dataWrapper', dataWrapperService);

一旦服务被 Angular 注入并且我在其上调用 data 方法,该方法将无法访问构造函数值。

// 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

但是……

我可以手动新建 dataWrapperService,效果很好。

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

我在这里错过了什么?

更新:


这似乎只发生在 Promise 回调中:

我通常像这样将函数传递给 then/catch

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

但只有以下方法有效:

$http.get('whatever').then((response) => smDataWrapper.data(response))

【问题讨论】:

    标签: angularjs ecmascript-6 angular-services


    【解决方案1】:

    Angular 在app.factory('dataWrapper', dataWrapperService); 需要一个函数,而不是一个类。

    您可以向您的类添加一个静态工厂方法并将其添加到app.factory。 (见下面代码sn-p的更新)

    这样的代码应该可以工作:

    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);
    

    更新

    因此,正如 cmets 中所述,您的代码应该可以工作,因为 ES6 类是一个构造函数,而这正是 angular.service 所期望的。

    稍后我会检查您的代码是否有任何其他问题。

    【讨论】:

    • 我以为 angular.service 采用了构造函数并在其上调用了“new”?
    • 是的,对不起,你是对的。我的代码适用于工厂。我会纠正的。我不知道你的代码有什么问题。我在您的代码中看到了许多类似的示例。
    • 这似乎只发生在 Promise 上。更新了上面的例子。
    • 这是不安全的,不会在 js minify 中存活
    【解决方案2】:

    我知道这已经晚了,但也许今天有人会像我一样遇到类似的问题,所以......

    实际上,这与承诺无关。当你这样做时:

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

    实际上,this 对象的功能不同。因此,当您尝试.then(function1) 时,实际上function1 被复制到参数successCallback 并且它的this 被更改。

    但是当你使用.then(() => function1())时,successCallback会收到你的lambda,而function1的实际this并没有丢失。

    所以如果你不知道,你做了什么从不在 javascript 中将函数分配给函数,而是使用 lambdas

    【讨论】:

    • 如果你想将一个服务类的方法分配给一个控制器函数,像$scope.isLoggedIn = () => { Auth.isLoggedIn(); };那样做,而不是$scope.isLoggedIn = Auth.isLoggedIn;。否则this 将指向控制器本身,而不是类。感谢大开眼界。
    • @arcol 前段时间我花了几个小时试图弄清楚这一点,很高兴我能免去别人的痛苦
    【解决方案3】:

    在 Angular 1.6.4 中,当我尝试注入在某个控制器中定义为类的服务时出现错误。

    不能将类作为函数调用

    因此,我想将函数用作服务。为了使其尽可能干净,我将导出一个立即返回实例化匿名类的函数。并在一个单独的文件中执行此操作,然后导入并使用该函数在另一个文件中创建服务。

    由于您要求将 ES6 与 Babel 一起使用,请使用 babel-plugin-angularjs-annotate 通过在导出函数上方添加 '/* @ngInject */' 来安全地注入依赖项。

    注入的服务$q$log 或通过闭包提供给类。 (无需在构造函数中传递它们并分配给它。)

    // dataWrapperService.js
    /* @ngInject */
    export const dataWrapperService = ($q, $log) => new class {
      constructor() {
        // do stuff
      }
    
      data() {
        // $q available through closure
        console.log($q)
      }
    }()
    
    // in your.module.js
    import angular from 'angular'
    
    import { dataWrapperService } from './dataWrapperService'
    
    export const YourModule = angular
      .module('yourmodule', [])
      .factory('dataWrapper', dataWrapperService)
      .name
    

    【讨论】:

      猜你喜欢
      • 2017-02-16
      • 2018-03-20
      • 1970-01-01
      • 2017-03-13
      • 2016-07-30
      • 1970-01-01
      • 2015-10-23
      • 1970-01-01
      • 2016-05-03
      相关资源
      最近更新 更多