Angular2依赖注入,在类继承过程中未注入服务

11
我正在使用 angular2Typescript。我尝试创建一个可以被其他类继承的基类,并在该基类中注入一个服务。到目前为止,我无法将ajaxService正确地注入到被继承user class中的base class中。具体来说,当实例化用户,然后从用户实例调用save()方法时,base class中的以下行:return _this._ajaxService.send(options);无法工作,因为_ajaxService未定义。

这里是一个扩展 base classuser class

import {Base} from '../utils/base';

export class User extends Base {

  // properties
  id = null;
  email = null;
  password = null;
  first_name = null;
  last_name = null;

  constructor(source) {
    _super.CopyProperties(source, this);
  }
}

这是基类

import {Component} from 'angular2/core';
import {AjaxService} from './ajax.service';

@Component({
  providers: [AjaxService]
})

export class Base {

  constructor(private _ajaxService: AjaxService) { }

  // methods
  public static CopyProperties(source:any, target:any):void {
    for(var prop in source){
      if(target[prop] !== undefined){
          target[prop] = source[prop];
      }
      else {
          console.error("Cannot set undefined property: " + prop);
      }
    }
  }

  save(options) {
    const _this = this;
    return Promise.resolve()
    .then(() => {
      const className = _this.constructor.name
                            .toLowerCase() + 's';
      const options = {
        data: JSON.stringify(_this),
        url: className,
        action: _this.id ? 'PATCH' : 'POST';
      };

      debugger;
      return _this._ajaxService.send(options);
    });
  }
}

除了没有将AjaxService注入基类之外,这个方法工作得很好。我想这是有道理的,因为实例化的是用户而不是基类。

那么,在另一个类上扩展Base module时,如何在Base module中使用AjaxService呢?

我猜当我实例化用户时,会调用用户类中的构造函数,但不会调用注入服务的基类中的构造函数。

这里是AjaxService

   import {Injectable} from 'angular2/core';

@Injectable()

export class AjaxService {

  // methods
  send(options) {
    const endpoint = options.url || "";
    const action = options.action || "GET";
    const data = options.data || {};

    return new Promise((resolve,reject) => {
      debugger;
      $.ajax({
        url: 'http://localhost:3000' + endpoint,
        headers: {
          Authentication: "",
          Accept: "application/vnd.app.v1",
          "Content-Type": "application/json"
        },
        data: data,
        method: action
      })
      .done((response) => {
        debugger;
        return resolve(response);
      })
      .fail((err) => {
        debugger;
        return reject(err);
      });
    });

  }

}

据我所知,可注入的对象(AjaxService)需要在TS中用@Injectable()进行注释。 - Günter Zöchbauer
你在哪里使用User类?它是一个组件吗?它有模板吗? - Yaron Schwimmer
2个回答

9

在基类中注入服务是可以的,但是你必须从User类传递它。你不能从Base继承服务的实例化,所以你必须从User向Base传递它。这不是TypeScript的限制,而是DI工作方式的特点。

像这样:

class User extends Base
  constructor(service: AjaxService) {
        super(service);
  }

如果Base为您实例化了服务,您将无法从User处影响实例化。这将抵消DI的许多好处,因为您通过将依赖控制委托给不同的组件而失去了控制权。
我理解您可能正在尝试通过在Base中指定此项来减少代码重复,但这违反了DI的原则。

谢谢你的回答。我正在尝试减少代码重复,但这将是一场噩梦... - Sam Jason Braddock

2

在Angular 2中,您想要注入的每个类都必须加上注释。如果它不是组件,则必须使用@Injectable()注释进行注释。如果您注入已经注入了其他类的类,则必须为其创建提供程序。

import {Injectable} from 'angular2/core';
import {Base} from './base';
@Injectable()
export class User extends Base {
}

我为您创建了Plunker,希望它能解决您的问题: http://plnkr.co/edit/p4o6w9GjWZWGfzA6cv41?p=preview (请查看控制台输出)
PS. 请使用Observable而不是Promises。

我认为只有在你想要注入到其他组件中的服务中才需要使用 @Injectable。 - monty_lennie
是的,没错。另外,您需要在组件的提供者数组中包含服务。 - Vlado Tesanovic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接