Несколько коллекций в Angular-in-memory-web-api

Как создать несколько коллекций, используя 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

Ответ 2

Подход, описанный в ответе Пола, верен, однако я упустил одну деталь, которую я хотел бы добавить: как правильно указать genId, чтобы он работал для обеих коллекций?

Ответ относится к примеру "Герои", написанному на TypeScript (расширенный набор JavaScript), в частности к главе 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;
  }
}

Теперь, если вы добавите 2-й сборник crises как показано в его ответе, то есть:

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

как вы предоставляете genId для обеих коллекций (при условии, что они относятся к типу Hero и Crises)? Перегрузка, как вы это делаете в C#, не работает в TypeScript, она выдает ошибку ("Реализация дублирующейся функции").


Решение: Я обнаружил, что вы можете решить эту проблему с помощью TypeScript Generics следующим образом. Замените genId функцию 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 extends Hero | Crises>: это означает, что тип T может быть либо Hero либо Crises: поэтому он будет вызываться, если переданный параметр имеет тип Hero[] или Crises[].

С этим знанием добавить 3-й, 4-й,... класс просто: просто добавьте класс. Скажем, мы хотим добавить класс SuperHero, тогда вы просто добавляете его через | 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.


Полезные ссылки: