Angular-in-memory-web-api中的多个集合

47

如何使用Angular-in-memory-web-api创建多个集合?对于单个集合没有问题,但我无法实现多个集合。

例如,我想在内存数据库中创建两个集合 - 国家和城市。有任何想法如何实现吗?

3个回答

73

只需返回一个包含两个数组的对象。在Angular示例中,你会看到类似下面的代码:

```javascript { heroes: HEROES, selectedHero: undefined } ```
createDb() {
  let heroes = [ .. ]
  return { heroes }
}

如果你还不知道,{ heroes }只是写成{ heroes: heroes }的简写。因此,如果您有两个集合,则只需将其添加为另一个属性即可。

createDb() {
  let heroes = [ .. ];
  let crises = [ .. ];
  return { heroes, crises };
  // or { heroes: heroes, crises: crises }
}

返回的属性名称将用于URL中的路径。因此,您可以使用

/api/heroes/1
/api/crises/1

太好了 - 但是 heroes example 也覆盖了 genId(heroes: Hero[]): number { ... }。现在我尝试过载它以使用 crises(即 genId(crises: Crises[]): number { ... }),但迄今为止没有成功("Duplicate function implementation")。你会怎么做?(在示例中,它返回最大id + 1以能够添加新项目) - Matt
终于找到了一种方法让它工作,并将其发布在这里作为您答案的附加信息。 - Matt

27
Paul的回答中所描述的方法是正确的,但是我漏掉了一个细节,我想要添加:如何正确指定genId,以使其适用于两个集合? 该答案涉及到使用TypeScript(JavaScript的超集)编写的“Heroes”示例,具体来说是HTTP章节。在那里,通过实现以下内容来模拟表格heroes
export class InMemoryDataService implements InMemoryDbService {
  createDb() {
    const heroes = [
      { id: 11, name: 'Mr. Nice' },
      { id: 12, name: 'Narco' },
      // ...
      { id: 20, name: 'Tornado' }
    ];
    return {heroes};
  }

  // Overrides the genId method to ensure that a hero always has an id.
  // If the heroes array is empty,
  // the method below returns the initial number (11).
  // if the heroes array is not empty, the method below returns the highest
  // hero id + 1.
  genId(heroes: Hero[]): number {
    return heroes.length > 0 ? Math.max(...heroes.map(hero => hero.id)) + 1 : 11;
  }
}

如果你按照他的回答添加一个第二个集合crises,即:

createDb() {
  let heroes = [ { ... }, ... ];
  let crises = [ { ... }, ... ];
  return { heroes, crises };
  // or { heroes: heroes, crises: crises }
}

我该如何为两个集合(假设它们的类型均为HeroCrises)提供genId?在TypeScript中,像在C#中一样进行重载是不起作用的,否则会抛出错误(“重复函数实现”)。

解决方案: 我发现可以使用TypeScript泛型来解决此问题。将原始的genId函数替换为以下通用版本:

genId<T extends Hero | Crises>(myTable: T[]): number {
  return myTable.length > 0 ? Math.max(...myTable.map(t => t.id)) + 1 : 11;
}

重要的是这部分:<T extends Hero | Crises>:它表示类型T可以是HeroCrises之一。因此,如果传递的参数类型为Hero[]Crises[]中的任意一个,则会调用该函数。

有了这个知识,添加第三个、第四个...类很简单:只需将类附加到列表中即可。例如,我们想要添加SuperHero类,那么你只需将其附加通过| SuperHero,代码会变成:

genId<T extends Hero | Crises | SuperHero>(myTable: T[]): number {
  return myTable.length > 0 ? Math.max(...myTable.map(t => t.id)) + 1 : 11;
}

注意: 作为前提,所有类HeroCrisesSuperHero)都需要声明一个数字类型的 id 属性。


有用的链接:


2
@ Matt,很高兴你已经包含了文档/相关文章的链接。 - Mwiza

0
补充一下,我不得不使用Partial,因为当完成英雄之旅第06课时,它一直提示我缺少一个id。我使用消息服务来查看代码停止工作的位置,所以您可以忽略this.log行,但是您可以将它们添加到自己的项目中以帮助调试。首先,我更新了addHero如下: addHero(hero: string): void { this.log(`In addHero of HeroesComponent, name is: ${hero}`);
if (!hero)
{
  this.log(`In if(!hero.name) of add hero: ${hero}`);
  return;
}

this.heroService.addHero({ name: hero } as Partial<Hero>)
  .subscribe(hero => {
    this.heroes.push(hero);
  });

}

然后我更新了heroes.service.ts文件,使用部分英雄并允许代码从in-memory-data.service.ts生成自己的id:

addHero(hero: Partial): Observable { this.log(`在addHero中:heroeName是:${hero.name}`); return this.http.post(this.heroesUrl, hero, this.httpOptions).pipe( tap((newHero: Hero) => this.log(`添加了带有字符串id=${newHero.id}的英雄`)), catchError(this.handleError("addHero错误"))); }

据我所见,现在它已经按预期工作。可能还有一些需要更新的代码,但这应该有助于解决以下错误消息的问题:

ERROR in src/app/heroes/heroes.component.ts:52:30 - error TS2352: Conversion of type '{ name: never; }' to type 'Hero' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Property 'id' is missing in type '{ name: never; }' but required in type 'Hero'.


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