Angular-in-memory-web-api 中的多个集合
Posted
技术标签:
【中文标题】Angular-in-memory-web-api 中的多个集合【英文标题】:Multiple collections in Angular-in-memory-web-api 【发布时间】:2017-03-02 00:05:44 【问题描述】:我们如何使用 Angular-in-memory-web-api 创建多个集合? 单一收藏不是问题。但我无法为多个集合实现它。
例如,我想在内存数据库中创建两个集合——国家和城市。任何想法,如何做到这一点?
【问题讨论】:
【参考方案1】:只需返回一个包含两个数组的对象。在 Angular 的示例中,您会看到类似
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 ...
),但到目前为止没有运气(“重复函数实现”)。你会怎么做? (在示例中,它返回最大 id + 1 以便能够添加新项目)
终于找到了让它工作的方法,并将其发布在here 作为您答案的附加信息。【参考方案2】:
Paul's answer 中描述的方法是正确的,但是我错过了一个我想补充的细节:你如何正确指定 genId
,所以它适用于两个集合?
答案是指用TypeScript(javascript 的超集)编写的“英雄”示例,特别是HTTP chapter。
在那里,通过实现模拟了一个表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
您如何为这两个集合提供genId
(假设它们的类型为Hero
和Crises
)?重载,就像您在 C#
中所做的那样,在 TypeScript 中不起作用,它会引发错误(“重复函数实现”)。
解决方案:
我发现,您可以使用 TypeScript's Generics 解决此问题,如下所示。将原来的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
类型可以是Hero
或Crises
:所以如果传递的参数是Hero[]
或@987654344类型,它将被调用@。
有了这些知识,添加 3rd、4th、... 类很简单: 只需附加类即可。假设我们要添加类SuperHero
,然后您只需通过| SuperHero
附加它,所以它看起来像:
genId<T extends Hero | Crises | SuperHero>(myTable: T[]): number
return myTable.length > 0 ? Math.max(...myTable.map(t => t.id)) + 1 : 11;
注意:作为先决条件,所有类(Hero
、Crises
和 SuperHero
)都需要声明一个数字 id
属性。
有用的链接:
HTTP chapter of Angular Tutorial
In-Memory-Web-API: Custom genId
Can You Specify Multiple Type Constraints For TypeScript Generics?
【讨论】:
@Matt,很高兴您提供了文档/相关文章的链接?【参考方案3】:除了这个讨论之外,我不得不使用 Partial,因为它一直说我在完成英雄之旅第 6 课时缺少一个 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);
);
然后我更新了 heros.service.ts 文件以使用部分 hero 并允许代码从 in-memory-data.service.ts 生成自己的 id:
addHero(hero: Partial): Observable
this.log(`In addHero: heroeName is: $hero.name`);
return this.http.post(this.heroesUrl, hero, this.httpOptions).pipe(
tap((newHero: Hero) =>
this.log(`added hero with string id=$newHero.id`)),
catchError(this.handleError("Error in 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'.
【讨论】:
以上是关于Angular-in-memory-web-api 中的多个集合的主要内容,如果未能解决你的问题,请参考以下文章
Angular - 如何将 ngFor 过滤到特定的对象属性数据
Angularjs2-zone.js:1382 GET http://localhost:3000/traceur 404 (Not Found)