Angular v17使用in-memory Web API遭遇HttpErrorResponse语法错误求助
问题概述
执行教程第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

