Зарегистрировать макет службы URL

В hero.service.ts файл для примера быстрого запуска Angular, шаг 7, это фрагмент кода:

@Injectable()
export class HeroService {

  private headers = new Headers({'Content-Type': 'application/json'});
  private heroesUrl = 'api/heroes';  // URL to web api

  constructor(private http: Http) { }

  getHeroes(): Promise<Hero[]> {
    return this.http.get(this.heroesUrl)
               .toPromise()
               .then(response => response.json().data as Hero[])
               .catch(this.handleError);
  }
}

Я попытался перевести его в свое приложение так:

@Injectable()
export class MyService {

  private headers = new Headers({'Content-Type': 'application/json'});
  private dataUrl = 'api/data';  // URL to web api

  constructor(private http: Http) { }

  getHeroes(): Promise<Hero[]> {
    return this.http.get(this.dataUrl) // <-- error here
               .toPromise()
               .then(response => response.json().data as MyData[])
               .catch(this.handleError);
  }
}

Я получил 404 - Collectionданныеnot found на this.http.get линия, которая вполне понятна, так как это просто случайный путь. Там нет API в этой конечной точке.

Вопрос: как работал пример Angular? Где он зарегистрировал api/heroes путь для ложных HTTP-запросов?

1 ответ

Решение

При использовании обычного модуля HTTP Angular, команда:

return this.http.get(this.dataUrl)

надеется this.dataUrl быть строкой, содержащей адрес реального веб-сервиса HTTP. (Такие как "http://swapi.co/api/people/1/".)

При "регулярном использовании" эта команда отправит запрос службе HTTP по адресу this.dataUrl,


Но... ваш код взят из учебника, который немного меняет вещи.


Если вы помните, учебник попросил вас добавить InMemoryWebApiModule на ваш @NgModule:

import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService }  from './in-memory-data.service';
...

@NgModule({
  imports: [
    ...
    InMemoryWebApiModule.forRoot(InMemoryDataService),
    AppRoutingModule
  ],
  ...
})

Те строки, которые вы добавляете, создают сервис, грубо говоря, перехватывают ваши http-запросы, не позволяя им достичь реального сервера URL, который вы даете (скажем, myserver.com/api/heroes), но вместо этого отправляю эти запросы на поддельный сервер.

(Для деталей, обратите внимание, что InMemoryWebApiModule происходит от angular-in-memory-web-api, Поэтому проверьте https://github.com/angular/in-memory-web-api чтобы понять, как это работает.)

Теперь этот поддельный сервер должен вернуть некоторые данные, чтобы быть полезным. Откуда это взялось?

Это где "вторая часть" InMemoryWebApiModule.forRoot(InMemoryDataService) а именно InMemoryDataService, вступает в игру.

В демоверсии Angular Docs обратите внимание, что InMemoryDataService определяется в './in-memory-data.service':

import { InMemoryDbService } from 'angular-in-memory-web-api';
export class InMemoryDataService implements InMemoryDbService {
  createDb() {
    const heroes = [
      { id: 0,  name: 'Zero' },
      ...
    ];
    return {heroes};
  }
}

Теперь важной частью здесь является возвращающая команда return {heroes};, (Если вы не знакомы с синтаксисом, это сокращение от return {heroes: heroes}; )

Ключи этого возвращаемого объекта определяют доступные URL на поддельном сервере.

Так как вы возвращаетесь {heroes: <something>} URL api/heroes будет доступен на поддельном сервере. Если вы вернулись {foo: <something>} затем URL api/foo будет доступно.

Как ты хочешь api/data быть доступным, а затем вернуть что-то вроде {data: ...} сделал бы:

createDb() {
  const data = [
    { id: 0, name: 'AAAA' },
    { id: 1, name: 'BBBB' },
    ...
  ];
  return {data};
}

Вот и все, это то, что вам нужно изменить.

Теперь имейте в виду, что для производственного (реального) кода вы должны удалить это целое InMemoryWebApiModule.forRoot(InMemoryDataService) вещь и иметь реальный веб-сервис, отвечающий на this.dataUrl,

Другие вопросы по тегам