You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular v17使用in-memory Web API遭遇HttpErrorResponse语法错误求助

Angular 17 使用 in-memory Web API 请求返回 index.html 引发 JSON 解析错误

问题概述

执行教程第6步时,通过HttpClient从in-memory Web API获取数据,构建成功但请求返回index.html文件,触发HttpErrorResponse,核心报错如下:

SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON...
响应文本为完整的<!doctype html>页面代码
错误消息:Http failure during parsing for http://localhost:4200/api/anime-list

当前环境为Angular v17,已将教程中的heroes替换为anime。

已尝试的排查动作:

  • 修改responseType为json/text
  • 增减请求URL中的api前缀
  • 调整路由路径中的api前缀
  • 重新排序路由优先级
  • 降级in-memory-web-api至低于0.18.0的版本
  • 切换到基于app.module.ts的传统配置替代独立路由/配置文件

疑问:该问题是否源于Angular 16与17的兼容差异?是否有其他开发者遇到类似问题?

相关代码片段

anime.service.ts

animeListUrl = 'api/anime-list';

getAnimeList(): Observable<Anime[]> {
    return this.http.get<Anime[]>(this.animeListUrl)
    .pipe(
      tap(_ => this.log('fetched animeList')), 
      catchError(this.handleError<Anime[]>('getAnimeList', [])));
  }

app.routes.ts

export const routes: Routes = [
    //{path: 'api/anime-list', component: AnimeComponent}
    {path: 'anime-list', component: AnimeComponent},
    {path: 'top-anime', component: DashboardComponent},
    {path: 'detail/:id', component: AnimeDetailComponent},
    {path: '', redirectTo: '/anime-list', pathMatch: 'full'},
    //{path: '', redirectTo: '/api/anime-list', pathMatch: 'full'}
];

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './in-memory-data.service';

import { AppRoutingModule } from './app-routing.module';

import { LoggingInterceptor } from './logging-interceptor';
import { IronHttpInterceptor } from './iron/iron-http-interceptor';

import { AppComponent } from './app.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { AnimeDetailComponent } from './anime-detail/anime-detail.component';
import { AnimeComponent } from './anime/anime.component';
import { MessagesComponent } from './messages/messages.component';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule,
    AppRoutingModule,
    HttpClientModule,

    // The HttpClientInMemoryWebApiModule module intercepts HTTP requests
    // and returns simulated server responses.
    // Remove it when a real server is ready to receive requests.
    HttpClientInMemoryWebApiModule.forRoot(
      InMemoryDataService, { dataEncapsulation: false }
    )
  ],
  declarations: [
    AppComponent,
    DashboardComponent,
    AnimeComponent,
    AnimeDetailComponent,
    MessagesComponent,
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: IronHttpInterceptor, multi: true }
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

解决方案与排查方向

1. 优先排查自定义拦截器干扰

你配置了LoggingInterceptor和IronHttpInterceptor两个全局拦截器,它们可能修改了请求头或请求路径,导致HttpClientInMemoryWebApiModule无法正确拦截/api/开头的请求。临时移除这两个拦截器的注册代码,测试请求是否恢复正常:

// 注释掉这部分代码测试
// providers: [
//   { provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptor, multi: true },
//   { provide: HTTP_INTERCEPTORS, useClass: IronHttpInterceptor, multi: true }
// ],

如果测试正常,需要调整拦截器逻辑,添加判断条件跳过对/api/前缀请求的处理,或者确保in-memory-web-api的拦截器优先级更高。

2. 升级in-memory-web-api至兼容Angular 17的版本

angular-in-memory-web-api@0.18.x版本发布时Angular 17尚未正式推出,存在兼容性问题。建议升级到最新版本(如0.19.0+),执行命令:

npm install angular-in-memory-web-api@latest

升级后重新启动项目测试。

3. 检查InMemoryDataService的数据定义

确保InMemoryDataService中返回的数据集合键名与请求URL的anime-list完全匹配,否则in-memory-web-api会返回404,触发Angular路由的fallback逻辑返回index.html:

export class InMemoryDataService implements InMemoryDbService {
  createDb() {
    const animeList = [
      // 示例数据
      { id: 1, name: 'Test Anime' }
    ];
    // 键名必须为'anime-list',对应请求URL的/api/anime-list
    return { 'anime-list': animeList };
  }
}

4. 验证路由配置的fallback行为

确保路由配置中没有将/api/前缀的路径指向组件,同时检查HttpClientInMemoryWebApiModule的passThruUnknownUrl参数是否设置为false(默认值),确保未知URL不会被转发到真实服务器,而是由in-memory-web-api处理:

HttpClientInMemoryWebApiModule.forRoot(
  InMemoryDataService, 
  { 
    dataEncapsulation: false,
    passThruUnknownUrl: false // 确保未匹配的请求被拦截
  }
)

结论

该问题主要由自定义拦截器干扰或in-memory-web-api版本与Angular 17不兼容导致,优先排查拦截器,再升级依赖版本,同时确认数据服务的配置正确性。已有不少Angular 17开发者反馈类似问题,升级in-memory-web-api到0.19.x版本后通常能解决。

内容的提问来源于stack exchange,提问作者Ricky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 04:00:06