前端入门HTTP请求实录:从零搭本地服务到对接大模型接口

0 阅读4分钟

近期我完成了两套可以落地的前端小项目:一套依靠 json‑server 搭建轻量化后端,实现人员表格的数据渲染;另一套直接调用DeepSeek的大模型开放接口。开发过程里我踩了不少新手高频遇到的bug,非常适合刚接触的同学参考。

浏览器发起请求的两套原生方案

前端网页向后端发起网络请求,有两套原生的可选API:XMLHttpRequest和fetch。 XMLHttpRequest推出时间较早,兼容性拉满,可以适配老旧浏览器,但是回调写法繁琐,多层请求嵌套时极易出现回调地狱,开发体验较差。 当下绝大多数工程都会选用fetch完成请求开发,它基于Promise实现,搭配 async/await 语法就可以轻松管控异步代码的执行顺序。这里有一个非常容易踩坑的细节:fetch只会捕获网络断开类的底层异常,服务端返回的404、500状态错误不会被catch捕获,上线前需要手动校验响应状态码。

零后端编码:json‑server快速启动本地接口

前后端本地联调的场景下,我们不需要搭建完整的Node后端服务,json‑server工具仅依靠一份json文件,就可以对外提供全套的接口能力。 我的后端目录中存放了 data.json ,它相当于整套项目轻量化的数据库,存储人员基础信息:

{
  "friends": [
    { "id":1, "name":"两只羊", "age": 19 },
    { "id":2, "name":"书包", "age": 19 }
  ]
}

我们在项目根目录的 package.json 内配置启动脚本,多余的 json‑serve 依赖可以直接移除:

{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "json-server --watch data.json --port 3000"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "json-server": "1.0.0-beta.15"
  }
}

终端运行 npm run dev 即可启动服务。 --watch 参数可以监听json文件的变更,文件更新之后接口返回的数据会同步刷新,3000是服务对外开放的端口。访问 http://localhost:3000/friends 就能够拿到全部人员数据。

人员表格页面的开发

后端服务运行完成之后,我们开始编写前端页面。首先完成 index.html 的基础页面结构搭建:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial‑scale=1.0">
  <title>Document</title>
</head>
<body>
  <header>
    <h1>前端发送http 请求</h1>
  </header>
  <main>
    <table>
      <thead>
        <tr>
          <th>id</th>
          <th>name</th>
          <th>age</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
  </main>
  <footer></footer>
  <script src="./main.js"></script>
</body>
</html>

页面内置一张人员信息表格,表头定义id、name、age三个字段,tbody节点用于渲染后端返回的表格行。

let friends = [];

async function loadData() {
  const endpoint = 'http://localhost:3000/friends';
  const res = await fetch(endpoint);
  const data = await res.json();
  console.log(data);
  return data;
}

function renderData(list) {
  console.log('renderData');
  const oBody = document.querySelector('table tbody');
  if (list.length > 0) {
    oBody.innerHTML = list.map(function(item) {
        console.log(item);
        return `
        <tr>
            <td>${item.id}</td>
            <td>${item.name}</td>
            <td>${item.age}</td>
        </tr>
        `
    }).join('')
  }
}

async function init() {
  console.log('init start');
  friends = await loadData();
  renderData(friends);
  console.log('init end')
}
init();

loadData函数负责发起网络请求、解析后端返回的json数据;renderData函数遍历数组,批量生成表格的DOM节点;init作为入口函数,统筹请求和页面渲染两个流程。

前端直连大模型的开放接口

本地人员表格项目调试完毕之后,我基于同样的fetch请求逻辑,实现了DeepSeek大模型接口的调用。大模型接口的底层通信逻辑和普通后端接口完全一致,仅在参数配置上有专属的规范。 我搭建了极简的展示页面 index.html :  

<!DOCTYPE html>
<html lang="zh‑CN">
<head>
  <meta charset="UTF‑8">
  <meta name="viewport" content="width=device‑width, initial‑scale=1.0">
  <title>DEEPSEEK接口调用</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div id="replay"></div>
  <script type="module" src="script.js"></script>
</body>
</html>

页面只预留了一个id为replay的容器,用于展示大模型返回的回答,脚本开启模块模式规避全局变量污染。 完整的请求逻辑写在 script.js 当中:

const endpoint = 'https://api.deepseek.com/chat/completions';
const headers = {
  'Content‑Type': 'application/json',
  'Authorization': 'Bearer 你的api'
}
const payload = {
  model: 'deepseek‑v4‑Flash',
  messages: [
    { role: 'system', content: 'You are a helpful assistant'},
    { role: 'user', content: '你好,DeepSeek'}
  ]
}
try {
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: headers,
    body: JSON.stringify(payload)
  })
  const data = await response.json();
  document.getElementById('replay').innerHTML = data.choices[0].message.content;
}catch(err){
  console.log(err)
}

一份完整的大模型请求由三部分构成:

1. 接口地址,也就是大模型服务商提供的服务入口;

2. 请求头,需要声明传输数据的格式为json,同时携带API密钥完成身份校验;

3. 请求体,内部配置模型名称、对话上下文数组,system字段用来设定AI的基础人设,user字段填入用户的提问。

这个项目里我遇到了前端请求非常经典的坑:fetch的body参数无法直接传入JavaScript对象,一开始我直接把payload对象放入请求体,后端完全无法读取参数,最后确认需要调用 JSON.stringify 将对象转为字符串后端才可以正常解析。

开发总结与后续方向

做完两套完整的demo之后,我对HTTP请求的底层逻辑有了非常直观的认知:HTTP请求的本质就是前端客户端向后端发起申请,后端返回对应数据,前端完成页面渲染。前后端分离已经是当下前端开发的主流方案,async/await语法极大降低了异步代码的编写门槛。