Зарегистрировать макет службы 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
,