Angular 示例

概述
本示例演示如何将 ApiSorcery 与 Angular 项目集成。Angular 是一个使用 TypeScript 构建 Web 应用程序的综合平台,提供依赖注入、RxJS 可观察对象和强大的 CLI 等强大功能。
特性
- 类型安全:完整的 TypeScript 支持,生成接口和类型
- RxJS 集成:与 Angular 的响应式编程模式无缝集成
- 依赖注入:使用 Angular 服务实现清晰的架构
- Axios 集成:内置支持 Axios HTTP 客户端和拦截器
- 智能提示支持:完整的 IDE 支持,包括自动完成和类型检查
- Tree shaking:通过 ES 模块支持优化打包体积
快速开始
1. 安装 ApiSorcery
bash
npm install -g autoapi2. 初始化配置
bash
autoapi init -l ts这将创建一个 .autoapirc.json 配置文件:
json
{
"application": {
"language": "ts",
"outputDir": "./src/app/api/auto"
},
"services": [
{
"code": "demo",
"token": "72735b33815c4e5c9c2a924a8f4907ef",
"version": 3,
"enabled": true,
"source": "https://your-api.com/swagger.json"
}
]
}3. 安装依赖
bash
npm install axios
npm install -D @types/node4. 生成 API 客户端
bash
autoapi generate5. 在 Angular 中使用
typescript
import { Component, OnInit } from '@angular/core';
import * as ApiUser from '@/app/api/auto/demo/ApiUser';
import type { User } from '@/app/api/auto/demo/model';
@Component({
selector: 'app-user-list',
templateUrl: './user-list.component.html',
styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit {
users: User[] = [];
loading = false;
ngOnInit() {
this.fetchUsers();
}
async fetchUsers() {
this.loading = true;
try {
const res = await ApiUser.getUserPaged({
pagination: {
page: 1,
limit: 10,
},
});
this.users = res.results || [];
} catch (error) {
console.error('获取用户失败:', error);
} finally {
this.loading = false;
}
}
}Angular 集成模式
创建 Angular 服务
typescript
// services/user.service.ts
import { Injectable } from '@angular/core';
import { Observable, from, BehaviorSubject } from 'rxjs';
import { map, catchError, tap } from 'rxjs/operators';
import * as ApiMain from '@/app/api/auto/demo/ApiMain';
import type { User } from '@/app/api/auto/demo/model';
@Injectable({
providedIn: 'root'
})
export class UserService {
private usersSubject = new BehaviorSubject<User[]>([]);
private loadingSubject = new BehaviorSubject<boolean>(false);
users$ = this.usersSubject.asObservable();
loading$ = this.loadingSubject.asObservable();
getUsers(): Observable<User[]> {
this.loadingSubject.next(true);
return from(ApiMain.getUsers()).pipe(
map(response => response.data || []),
tap(users => {
this.usersSubject.next(users);
this.loadingSubject.next(false);
}),
catchError(error => {
this.loadingSubject.next(false);
console.error('获取用户失败:', error);
throw error;
})
);
}
getUserById(id: string): Observable<User> {
return from(ApiMain.getUserById(id)).pipe(
map(response => response.data)
);
}
createUser(userData: Partial<User>): Observable<User> {
return from(ApiMain.createUser(userData)).pipe(
map(response => response.data),
tap(() => this.getUsers().subscribe())
);
}
}在组件中使用服务
typescript
// components/user-list/user-list.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { UserService } from '@/app/services/user.service';
import type { User } from '@/app/api/auto/main/model';
@Component({
selector: 'app-user-list',
templateUrl: './user-list.component.html',
styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit, OnDestroy {
users: User[] = [];
loading = false;
private destroy$ = new Subject<void>();
constructor(private userService: UserService) {}
ngOnInit() {
this.userService.users$
.pipe(takeUntil(this.destroy$))
.subscribe(users => this.users = users);
this.userService.loading$
.pipe(takeUntil(this.destroy$))
.subscribe(loading => this.loading = loading);
this.userService.getUsers().subscribe();
}
ngOnDestroy() {
this.destroy$.next();
this.destroy$.complete();
}
refresh() {
this.userService.getUsers().subscribe();
}
}组件模板
html
<!-- user-list.component.html -->
<div class="user-list">
<div *ngIf="loading" class="loading">
<p>加载中...</p>
</div>
<ul *ngIf="!loading" class="users">
<li *ngFor="let user of users; trackBy: trackByUserId">
{{ user.name }}
</li>
</ul>
<button (click)="refresh()" [disabled]="loading">
刷新
</button>
</div>使用 Angular Signals(Angular 16+)
typescript
import { Component, OnInit, signal, computed } from '@angular/core';
import * as ApiMain from '@/app/api/auto/demo/ApiMain';
import type { User } from '@/app/api/auto/demo/model';
@Component({
selector: 'app-user-list',
templateUrl: './user-list.component.html',
standalone: true
})
export class UserListComponent implements OnInit {
users = signal<User[]>([]);
loading = signal(false);
error = signal<string | null>(null);
userCount = computed(() => this.users().length);
ngOnInit() {
this.fetchUsers();
}
async fetchUsers() {
this.loading.set(true);
this.error.set(null);
try {
const response = await ApiMain.getUsers();
this.users.set(response.data || []);
} catch (err) {
this.error.set(err instanceof Error ? err.message : '获取用户失败');
} finally {
this.loading.set(false);
}
}
}最佳实践
- 类型定义:利用生成的 TypeScript 接口提高类型安全性
- Angular 服务:将 API 调用封装在可注入的服务中以实现可重用性
- RxJS 操作符:使用 RxJS 操作符进行数据转换和错误处理
- 依赖注入:利用 Angular 的 DI 系统实现清晰的架构
- 取消订阅模式:始终取消订阅可观察对象以防止内存泄漏
- 错误处理:使用 Angular 的错误拦截器实现适当的错误处理
- 环境配置:使用 Angular 环境文件配置不同的 API 端点
- 懒加载:实现模块的懒加载以优化打包体积