使用http get(RC1和TS)

时间:2016-06-26 15:20:37

标签: http typescript angular

我在从后端发出http请求时丢失了数据。我试图让一个plunker来展示我的问题,但我没有让它工作,配置有些问题?但是,只有必要的代码才能展示我的问题:Plunker

好吧,我试图用本地Json展示我的问题,但实际上我有一个实际的后端。检索单个英雄时,问题在于服务。这就是我丢失数据的地方。

Hero类的一部分:

export class Hero {

  private powers: Array<Power>;

  constructor(public id: string, public name: string) {
    this.powers = new Array<Power>();
  }
}

一位英雄的Json示例:

{
  "id":"randomString",
  "name":"heroName",
  "powers":[
    {
      "text":"power",
      "value":"1"
    }
  ]
}

在执行getById方法时,我需要将传入的数据指定为新的英雄,然后将数组遗留给powers,因为它在Hero类中是私有的只能指定英雄的身份和姓名:

  public getById(id: string) {
    return this.http.get('/app/hero.json')
      .map((res: Response) => res.json())
      //without following line it gives self.context error:
      .map(res => new Hero(res.id, res.name))
  }

所以我失去了数据阵列和数组中的所有数据,因为每次我检索一个英雄时它都会创建一个新的Powers数组。当然,我想要Hero对象中的所有数据!

所以在这个示例app中我忽略了使用id,只是返回一个英雄。我注意到在打印到控制台时,在这个例子中完全忽略了powers数组,但是在我的实际应用中它会创建一个新数组!顺便说一句,在我的实际应用程序中,我的方法看起来像这样:

getById(id: string) {
    return this.http.get('someURL' + id)
        //.map((res: Response) => {console.log('res', res);}); // <--- logs correct data including powers that is populated with data!
        .map((res: Response) => res.json())
        //unless this following line is added, it gives error "self.context...", BUT I lose data!

        .map(hero => new hero(hero.id, hero.name));
}

我试图过滤英雄,但它不起作用!

  //undefined
  getById(id: string){
    return this.http.get('/app/heroes.json')
    .map(heroes => this.heroes.filter(hero => hero.id === id)[0]);
  }

所以我真的不知道如何前进,如何获取存储在powers数组中的数据,而不仅仅是英雄的名字和id。

2 个答案:

答案 0 :(得分:1)

您的Hero类有两个参数,idname。由于您只传递了这两个参数,因此JSON上的powers数组永远不会被使用。 您可以添加可选的powers参数:

class Hero {

    constructor(public id: string, 
                public name: string, 
                private powers: Power[] = []) {}
}

请注意语法:private powers: Power[] = []。这使得powers成为可选参数,其默认值为空数组。这与您使用this.powers = new Array<Power>();完全一样,除非它允许您传入一组权力(如果它们已经存在)。

查看您的plunkr,唯一的问题是您已将Power声明为类,这意味着您必须在每个项目上调用new Power()在将JSON传递给构造函数之前,在JSON上的powers数组中。如果权力本身实际上没有类方法,您可以将其更改为接口以保留类型,同时使实例化更容易:

interface Power {
    text: string;
    value: string;
}

getById函数中,您只需要添加powers参数:

  public getById(id: string) {
    return this.http.get('/app/hero.json')
      .map((res: Response) => res.json())
      .map(res => new Hero(res.id, res.name, res.powers))
  }

如果确实需要Power作为类,另一个选项是向专门用于服务器响应的Hero类添加静态方法:

class Hero {

    constructor(public id: string,
                public name: string,
                private powers: Power[] = []) {}


    static initFromJSON(json): Hero {

        let id = json.id;
        let name = json.name;
        let powers: Power[] = json.powers.map(power => new Power(power.text, power.value));
        return new Hero(id, name, powers);
    }
}

然后您可以将getById功能设为:

public getById(id: string) {
    return this.http.get('/app/hero.json')
        .map((res: Response) => res.json())
        .map(res => Hero.initFromJSON(res))
}

答案 1 :(得分:0)

上面的答案可以作为一个魅力,但一直在玩我的代码,我也想出了以下内容。因此,如果数组PowerHero类中是私有的,那么这是另一种解决方案。

无需更改课程,因此保持不变:

export class Hero {

  private powers: Array<Power>;

  constructor(public id: string, public name: string) {
    this.powers = new Array<Power>();
  }
}

getById方法与上面答案中的第二个方法相同:

public getById(id: string) {
    return this.http.get('/app/hero.json')
        .map((res: Response) => res.json())
        .map(res => Hero.heroFromJSON(res))
}

将此静态方法添加到Hero类:

static heroFromJSON(json) {
    let hero = Object.create(Hero.prototype);
    return Object.assign(hero, json, { powers: new Array<Power>(json.powers) })
}