ncaught(承诺):错误:./Search类中的错误搜索 - 内联模板:4:0导致:超出最大调用堆栈大小

时间:2016-09-17 14:26:57

标签: javascript json angular typescript

我是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';

我完全没有其他的猜测为什么这是失败而不是代码中的无限期函数,但我无法弄清楚,在哪里。因此,任何提示和帮助将非常感谢!谢谢!

1 个答案:

答案 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>

看看这是否有帮助。