☰
写给前端的 Nest.js 教程——10分钟上手后端接口开发与 TaoToken 统一 Key 配置
2026/9/30 19:49:23 网站建设 项目流程

1. 前端写接口为什么总卡在第一步:Nest.js 到底能帮你做什么

如果你写过 Vue 或 React,大概率遇到过这种场景:页面画完了,数据没地方来。要么等后端同事排期,要么自己用 Express 随手糊一个app.get('/api/list'),结果越写越乱,路由、参数校验、数据库操作全堆在一个文件里。Nest.js 就是来解决这个问题的——它把后端项目拆成 Module、Controller、Service 三层,每层职责清晰,写起来像搭积木。

Nest.js 是一个基于 Node.js 的服务端框架,底层默认跑 Express,也支持 Fastify。它内置 TypeScript 支持,用装饰器语法描述路由和依赖注入。对前端来说,装饰器不陌生,Angular 和 Vue 的 Class API 里都见过类似写法。你不需要理解 IoC 的完整理论,只要知道:Controller 负责接请求,Service 负责干活,Module 负责把它们组装在一起。

这篇文章面向有前端基础、想快速补齐后端接口能力的开发者。我会带你从零搭一个可运行的 REST 接口服务,包含用户增删改查,最后把模型调用凭证统一到 TaoToken,这样你以后调模型不用到处翻 Key。整个过程 10 分钟左右能跑通,代码可以直接复制。

适合谁看:会 JavaScript/TypeScript、用过 npm、了解 HTTP 基本概念的前端。不需要 MongoDB 经验,我会给最简配置。如果你之前只写过前端路由,把 Controller 理解成“后端版路由表”就行。

2. 环境准备与 TaoToken 统一 Key 配置:把模型调用凭证收口

在开始写接口之前,先把环境搭好。你需要 Node.js 版本 >= 16,npm 或 yarn 都行。我习惯用 pnpm,但下面命令用 npm 写,兼容性最好。

第一步,安装 Nest CLI:

npm i -g @nestjs/cli nest new nest-api-demo

执行后会让你选包管理器,选 npm 即可。创建完成后进入目录:

cd nest-api-demo npm run start:dev

看到Nest application successfully started就说明服务跑起来了,默认监听 3000 端口。浏览器打开http://localhost:3000会看到 Hello World。

接下来处理 TaoToken 的 Key 配置。为什么要在 Nest 项目里配这个?因为很多前端同学在写接口时,会顺手加一个“调模型”的接口,比如让后端代理请求大模型,避免把 Key 暴露在浏览器里。这时候如果每个项目都去环境变量里翻 Key,很容易乱。TaoToken 提供统一的 API 入口,你只需要一个 Key,就能在多个项目里复用。

先到 TaoToken 控制台创建一个 API Key。地址是https://taotoken.net/api-keys,登录后点“创建密钥”,复制生成的 Key。注意不要提交到 Git。

然后在项目根目录创建.env文件:

TAOTOKEN_API_KEY=sk-你的实际Key TAOTOKEN_BASE_URL=https://taotoken.net/api

安装 dotenv 和 axios:

npm install dotenv axios

在src/main.ts顶部引入 dotenv:

import 'dotenv/config'; import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); await app.listen(3000); } bootstrap();

这样后续在 Service 里就能通过process.env.TAOTOKEN_API_KEY读取。如果你用的是 Claude Code 或 Cline 这类工具,配置方式类似,Base URL 填https://taotoken.net/api,Key 填同一个,Model ID 按需选择。三件套保持一致,切换项目时不用改代码。

3. 可复制配置:Module/Controller/Service 分层与模型调用片段

现在开始写代码。先创建一个用户模块:

nest g module user nest g controller user nest g service user

Nest CLI 会自动在src/user下生成三个文件,并在app.module.ts里注册 UserModule。打开src/user/user.module.ts,确认 imports 里有 UserModule。

先定义数据接口。创建src/user/user.interface.ts:

export interface User { id: string; name: string; email: string; }

为了演示简单,我用内存数组存数据,不接数据库。创建src/user/user.service.ts:

import { Injectable } from '@nestjs/common'; import { User } from './user.interface'; @Injectable() export class UserService { private users: User[] = [ { id: '1', name: '张三', email: 'zhangsan@example.com' }, ]; findAll(): User[] { return this.users; } findOne(id: string): User { return this.users.find((u) => u.id === id); } create(user: Omit<User, 'id'>): User { const newUser = { id: Date.now().toString(), ...user }; this.users.push(newUser); return newUser; } update(id: string, user: Partial<User>): User { const index = this.users.findIndex((u) => u.id === id); if (index === -1) return null; this.users[index] = { ...this.users[index], ...user }; return this.users[index]; } remove(id: string): boolean { const index = this.users.findIndex((u) => u.id === id); if (index === -1) return false; this.users.splice(index, 1); return true; } }

接着写 Controller,src/user/user.controller.ts:

import { Controller, Get, Post, Put, Delete, Param, Body, } from '@nestjs/common'; import { UserService } from './user.service'; import { User } from './user.interface'; @Controller('user') export class UserController { constructor(private readonly userService: UserService) {} @Get() findAll(): User[] { return this.userService.findAll(); } @Get(':id') findOne(@Param('id') id: string): User { return this.userService.findOne(id); } @Post() create(@Body() body: Omit<User, 'id'>): User { return this.userService.create(body); } @Put(':id') update(@Param('id') id: string, @Body() body: Partial<User>): User { return this.userService.update(id, body); } @Delete(':id') remove(@Param('id') id: string): { success: boolean } { return { success: this.userService.remove(id) }; } }

现在加一个模型调用接口,演示 TaoToken 配置。在src/user/user.service.ts里加一个方法:

import axios from 'axios'; async chatWithModel(prompt: string): Promise<string> { const response = await axios.post( `${process.env.TAOTOKEN_BASE_URL}/v1/chat/completions`, { model: 'gpt-4o-mini', messages: [{ role: 'user', content: prompt }], }, { headers: { Authorization: `Bearer ${process.env.TAOTOKEN_API_KEY}`, 'Content-Type': 'application/json', }, }, ); return response.data.choices[0].message.content; }

在 Controller 里加一个 POST 路由:

@Post('chat') async chat(@Body('prompt') prompt: string): Promise<{ reply: string }> { const reply = await this.userService.chatWithModel(prompt); return { reply }; }

注意:@Post('chat')要放在@Post()之前,否则chat会被当成:id参数。这是 Nest 路由匹配顺序的坑,我踩过。

4. 验证请求与成功结果:用 curl 和 Postman 跑通接口

服务启动后,用 curl 测试。先测用户列表:

curl http://localhost:3000/user

返回:

[{"id":"1","name":"张三","email":"zhangsan@example.com"}]

创建用户:

curl -X POST http://localhost:3000/user \ -H "Content-Type: application/json" \ -d '{"name":"李四","email":"lisi@example.com"}'

返回新用户对象,id 是时间戳。

测试模型调用接口:

curl -X POST http://localhost:3000/user/chat \ -H "Content-Type: application/json" \ -d '{"prompt":"用一句话解释什么是REST API"}'

如果配置正确,会返回类似:

{"reply":"REST API 是一种基于 HTTP 协议的接口设计风格,用 URL 定位资源,用方法表示操作。"}

如果报 401,检查.env里的 Key 是否复制完整,有没有多余空格。如果报Cannot find module 'dotenv/config',确认npm install dotenv执行成功,并且main.ts第一行就引入了。

Postman 操作更直观:新建请求,方法选 POST,URL 填http://localhost:3000/user/chat,Body 选 raw JSON,填入 prompt,发送即可。看到 reply 字段就说明整条链路通了。

5. 本篇常见错排查:401、local proxy failed、reading choices 怎么解

第一个常见错误:401 Unauthorized。原因通常是 Key 没读到或格式不对。检查.env文件是否在项目根目录,main.ts是否在NestFactory.create之前引入了dotenv/config。另外确认请求头是Bearer sk-xxx,Bearer 和 Key 之间有一个空格。

第二个:local proxy failed或连接超时。这通常是因为 Base URL 写错了。TaoToken 的 API 地址是https://taotoken.net/api,不要多加/v1,因为代码里已经拼了/v1/chat/completions。如果你在别的工具里配置,比如 Cline 的 MCP 设置,Base URL 同样填这个,Model ID 按工具要求填。

第三个:Cannot read properties of undefined (reading 'choices')。这说明响应结构和你预期的不一样。先打印response.data看看实际返回。常见原因是模型名称写错,或者请求体格式不对。TaoToken 兼容 OpenAI 格式,messages数组里每条要有role和content。

第四个:Nest 启动时报Nest can't resolve dependencies of the UserService。检查user.module.ts的 providers 里有没有写 UserService,Controller 里有没有通过构造函数注入。Nest 的依赖注入要求显式声明。

第五个:路由 404。确认 Controller 上的@Controller('user')和方法的@Get()拼起来的路径。比如@Get(':id')会匹配/user/1,但不会匹配/user/chat,所以 chat 路由要放在前面。

如果遇到 OAuth 相关报错,比如OAuth token exchange failed,那通常是工具侧的认证流程问题,和 Nest 代码无关。检查你用的客户端是否支持自定义 Base URL,TaoToken 的接入文档里有各工具的配置示例,地址是https://taotoken.net/doc。

6. 从接口到模型调用:把 TaoToken 接入你的日常开发流

接口跑通后,你可以把 TaoToken 的配置复制到其他项目。比如你在用 Claude Code 做代码补全,或者用 Cline 做 Agent 任务,Base URL 和 Key 保持一致即可。Coding Plan 适合长期编码场景,模型对话适合临时验证,API Keys 页面管理所有凭证。

我自己的习惯是:本地开发用.env,CI 环境用环境变量注入,永远不把 Key 写进代码。Nest 项目里所有需要调模型的地方,都走同一个 Service 方法,这样换模型或换供应商时只改一处。

最后提醒一点:@Post('chat')和@Post()的顺序问题,以及@Get(':id')会吞掉后续静态路由,这两个坑在新手阶段最容易遇到。记住“具体路径放前面,参数路径放后面”就行。

代码写完后,用npm run start:dev保持热重载,改完文件自动重启。测试接口时先看控制台日志,Nest 会把每个请求的方法和路径打出来,方便定位。如果响应慢,先确认是不是模型调用本身耗时,可以在 Service 里加console.time打点。

到这里,一个带用户 CRUD 和模型调用的 Nest 后端就完成了。你可以把它当成模板,后续加数据库、加鉴权、加日志,都是在这个骨架上扩展。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询