我是Angular2的新手并且正在开发一个webapp。在这个webapp中,我想对REST API执行三种不同的调用。为了测试这个,我“嘲笑”针对三个文件的API调用,包含三个应该返回数据的JSON对象。它没有按预期工作,因为我在开发人员控制台中收到以下错误消息:
ncaught(承诺):错误:./Search类中的错误搜索 - 内联模板:4:0导致:超出最大调用堆栈大小
请参阅以下代码:
模板 - search.template.html:
<search>
<h1>Angular2 HTTP Demo App</h1>
<h2>Foods</h2>
<ul>
<li *ngFor="let food of foods"><input type="text" name="food-name" [(ngModel)]="food.name"><button (click)="updateFood(food)">Save</button> <button (click)="deleteFood(food)">Delete</button></li>
</ul>
<p>Create a new food: <input type="text" name="food_name" [(ngModel)]="food_name"><button (click)="createFood(food_name)">Save</button></p>
<h2>Books and Movies</h2>
<h3>Books</h3>
<ul>
<li *ngFor="let book of books">{{book.title}}</li>
</ul>
<h3>Movies</h3>
<ul>
<li *ngFor="let movie of movies">{{movie.title}}</li>
</ul>
</search>
搜索服务,执行API调用 - search.service.ts:
import { Injectable } from '@angular/core';
import 'rxjs/add/operator/map'
import { Observable } from 'rxjs/Observable';
import { Http, Response, Headers, RequestOptions } from "@angular/http";
import 'rxjs/add/observable/forkJoin';
import 'rxjs/add/observable/of';
@Injectable()
export class SearchService {
constructor(private http:Http) {
}
// Uses http.get() to load a single JSON file
getFoods() {
return this.http.get('./food.json').map((res:Response) => res.json());
}
// Uses Observable.forkJoin() to run multiple concurrent http.get() requests.
// The entire operation will result in an error state if any single request fails.
getBooksAndMovies() {
return Observable.forkJoin(
this.http.get('./books.json').map((res:Response) => res.json()),
this.http.get('./movies.json').map((res:Response) => res.json())
);
}
createFood(food) {
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
let body = JSON.stringify(food);
// Note: This is only an example. The following API call will fail because there is no actual API to talk to.
//return this.http.post('/api/food/', body, headers).map((res:Response) => res.json());
}
updateFood(food) {
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({headers: headers});
let body = JSON.stringify(food);
// Note: This is only an example. The following API call will fail because there is no actual API to talk to.
//return this.http.put('/api/food/' + food.id, body, headers).map((res:Response) => res.json());
}
deleteFood(food) {
// Note: This is only an example. The following API call will fail because there is no actual API to talk to.
//return this.http.delete('/api/food/' + food.id);
}
}
搜索组件类 -
search.component.ts:
import {Component, Output, EventEmitter, OnInit} from '@angular/core';
import { SearchService } from '../search/search.service';
import { AppState } from '../app.service';
import { HomeService } from '../home/home.service';
import { Injectable } from '@angular/core';
import { URLSearchParams, Jsonp } from '@angular/http';
import { Observable } from 'rxjs/Observable';
@Component({
// The selector is what angular internally uses
// for `document.querySelectorAll(selector)` in our index.html
// where, in this case, selector is the string 'home'
selector: 'search', // <home></home>
// We need to tell Angular's Dependency Injection which providers are in our app.
providers: [
HomeService,
SearchService
],
//
directives: [CORE_DIRECTIVES],
// Our list of styles in our component. We may add more to compose many styles together
//styleUrls: [ ],
// Every Angular template is first compiled by the browser before Angular runs it's compiler
templateUrl: 'search.template.html'
})
export class Search {
public foods;
public books;
public movies;
public food_name;
constructor(private _searchService: SearchService) { }
ngOnInit() {
this.getFoods();
this.getBooksAndMovies();
}
getFoods() {
this._searchService.getFoods().subscribe(
// the first argument is a function which runs on success
data => { this.foods = data},
// the second argument is a function which runs on error
err => console.error(err),
// the third argument is a function which runs on completion
() => console.log('done loading foods')
);
}
getBooksAndMovies() {
this._searchService.getBooksAndMovies().subscribe(
data => {
this.books = data[0]
this.movies = data[1]
}
// No error or completion callbacks here. They are optional, but
// you will get console errors if the Observable is in an error state.
);
}
/*createFood(name) {
let food = {name: name};
this._searchService.createFood(food).subscribe(
data => {
// refresh the list
this.getFoods();
return true;
},
error => {
console.error("Error saving food!");
return Observable.throw(error);
}
);
}
updateFood(food) {
this._searchService.updateFood(food).subscribe(
data => {
// refresh the list
this.getFoods();
return true;
},
error => {
console.error("Error saving food!");
return Observable.throw(error);
}
);
}
deleteFood(food) {
if (confirm("Are you sure you want to delete " + food.name + "?")) {
this._searchService.deleteFood(food).subscribe(
data => {
// refresh the list
this.getFoods();
return true;
},
error => {
console.error("Error deleting food!");
return Observable.throw(error);
}
);
}
}*/
/*
@Output() addVehicle = new EventEmitter();
// Set our default values
localState = { value: '' };
vehicles= [
{
id: 0,
name: 'TEST'
}
];
// TypeScript public modifiers
constructor(public appState: AppState, private homeService: HomeService) {
// this.appState.set('value', value);
}
add(_event) {
console.log('adding ', _event);
this.addVehicle.emit({
value: _event
});
}
constructor(private _dataService: DataService) { }
ngOnInit() {
this.getAllItems();
}
private getAllItems(): void {
this._dataService
.GetAll()
.subscribe((data:MyTypedItem[]) => this.myItems = data,
error => console.log(error),
() => console.log('Get all Items complete'));
}
ngOnInit() {
console.log('hello `Home` component');
}
*/
}
movies.json:
[
{ "title": "Ghostbusters" },
{ "title": "Star Wars" },
{ "title": "Batman Begins" },
{ "title": "Bourne Identity" },
{ "title": "Bourne Identity 2" }
]
food.json:
[
{ "id": 1, "name": "Donuts" },
{ "id": 2, "name": "Pizza" },
{ "id": 3, "name": "Sushi" }
]
books.json:
[
{ "title": "Hitchhiker's Guide to the Galaxy" },
{ "title": "The Fellowship of the Ring" },
{ "title": "Moby Dick" }
]
index.ts:
export * from './search.component';
我完全没有其他的猜测为什么这是失败而不是代码中的无限期函数,但我无法弄清楚,在哪里。因此,任何提示和帮助将非常感谢!谢谢!
答案 0 :(得分:1)
从search.template.html
,删除<search>
标记。由于你的html模板中的搜索标签,它是递归的。因此,您将收到超出最大调用堆栈大小的错误。
保留这样的模板 -
<h1>Angular2 HTTP Demo App</h1>
<h2>Foods</h2>
<ul>
<li *ngFor="let food of foods"><input type="text" name="food-name" [(ngModel)]="food.name"><button (click)="updateFood(food)">Save</button> <button (click)="deleteFood(food)">Delete</button></li>
</ul>
<p>Create a new food: <input type="text" name="food_name" [(ngModel)]="food_name"><button (click)="createFood(food_name)">Save</button></p>
<h2>Books and Movies</h2>
<h3>Books</h3>
<ul>
<li *ngFor="let book of books">{{book.title}}</li>
</ul>
<h3>Movies</h3>
<ul>
<li *ngFor="let movie of movies">{{movie.title}}</li>
</ul>
看看这是否有帮助。