LLM服务HTTP接口实战:前端HTTP请求全解与项目落地

一、前言

在对接LLM大模型服务、后端业务接口开发中,HTTP接口调用是前端必备核心能力 。日常开发里主要分为两种调用方案:基于OpenAI官方SDK封装调用、原生fetch发起网络请求;同时前端原生还存在XMLHttpRequest老牌请求方案。本文围绕客户端-服务器架构、DNS与域名原理、本地Mock服务搭建、异步语法async/await、数据渲染全链路完整讲解,配套可运行实战项目。

二、前端发起HTTP请求的主流实现方案

2.1 两大原生请求API

前端浏览器环境原生提供两套发起HTTP请求的底层API,是所有请求库(axios、openai-sdk)的底层实现基础:

  1. XMLHttpRequest(XHR):早期JS异步请求标准,AJAX技术底层依托该API实现,兼容全量低版本浏览器;
  2. Fetch API:ES6推出新标准,基于Promise设计,语法更简洁,现代浏览器原生支持,也是对接LLM HTTP接口最常用原生方案。
请求方案 底层设计 优点 适用场景
XMLHttpRequest 回调设计 兼容性极强,IE可用 老旧项目维护、兼容低版本设备
fetch Promise+异步语法 语法精简、原生支持async/await 新项目、对接LLM/后端REST接口

2.2 开发对应的编程架构模式

2.2.1 前后端分离架构

本文所有代码基于前后端分离模式:前端只负责页面渲染、交互逻辑,后端(Node/Java)专注接口开发、数据处理,通过约定的HTTP接口+JSON格式完成数据交互,也是目前对接OpenAI、各类LLM HTTP接口的主流架构。

2.2.2 异步编程:async/await语法

fetch本身基于Promise异步设计,async/await是ES2017推出的异步语法糖,可以把异步代码书写成同步代码的结构,解决多层Promise链式调用可读性差的问题,是LLM接口请求、后端接口数据拉取的标准写法。

核心作用:await强制阻塞当前代码,等待接口请求、数据解析完成后,再向下执行渲染逻辑。

2.3 客户端/服务端(C/S)与浏览器/服务端(B/S)架构

  1. B/S(Browser/Server 浏览器-服务器):用户通过浏览器访问页面,前端代码运行在浏览器,本文HTML+JS项目属于该架构;
  2. C/S(Client/Server 客户端-服务器):Android、IOS原生App作为客户端,同样通过HTTP调用后端/LLM服务接口。

不管B/S还是C/S,客户端和服务端通信底层统一使用HTTP协议,对接LLM接口无架构区分。

三、Server服务基础原理

3.1 服务器组成

一台可提供接口服务的Server由两部分构成:

  1. 硬件:物理服务器/云服务器;
  2. 软件:后端运行环境,常见Java、Node.js、Go等开发语言。

3.2 IP地址 + 端口号

示例地址:http://127.0.0.1:3000

  • IP地址 :网络中设备唯一标识,用来在互联网/局域网精准定位目标服务器;127.0.0.1是本机回环地址,仅本地电脑可访问;
  • 端口号 :一台服务器可开启多个服务,端口用来区分同一机器上不同应用,示例3000为自定义服务端口,取值范围0~65535。

3.3 域名与DNS解析

IP由一串数字组成难以记忆,因此出现域名 (如www.baidu.com);

DNS解析:域名系统自动将易记的域名翻译为对应的IP地址,浏览器才能通过IP找到目标服务器。对接线上LLM接口时,填写域名URL即可,底层自动完成DNS解析。

3.4 API URL(Endpoint接口终点)

Endpoint即接口请求终点,是后端预先定义好的接口地址(例如http://localhost:3000/friends、OpenAI大模型接口https://api.openai.com/v1/chat/completions)。

前端固定请求该地址,后端收到请求后处理逻辑、返回JSON数据,项目开发中所有接口地址统一配置管理,方便后期环境切换(测试/生产LLM地址)

3.5 数据流转规则

后端接口统一返回JSON格式数组/对象 ,前端拿到数组后,通过Array.map()遍历数组,拼接HTML字符串,最终插入表格DOM完成页面渲染,也是本案例核心数据处理逻辑。

map() 方法创建一个新数组,这个新数组由原数组中的每个元素 都调用一次提供的函数后的返回值组成

示例:

javascript 复制代码
const array1 = [1, 4, 9, 16];
const map1 = array1.map((x) => x * 2);
console.log(map1); // [2, 8, 18, 32]

开发查阅建议:原生Fetch、DOM操作细节优先参考MDN官方文档,API参数、异常处理最全。

四、本地Mock服务环境搭建(json-server)

项目使用json-server快速搭建本地RESTful模拟服务,无需编写后端代码,一键生成接口,用来模拟LLM/后端真实接口环境。

注:可以在终端中输入pnpm i json-server

4.1 package.json配置文件

新建项目,初始化依赖配置,执行npm init -y安装依赖,npx json-server data.json启动3000端口服务。

json 复制代码
{
  "name": "backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "json-server --watch data.json --port 3000"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "type": "commonjs",
  "dependencies": {
    "json-server": "1.0.0-beta.15"
  }
}
  • --watch data.json:监听本地json文件,文件数据改动自动更新接口返回值;
    注:这里data.json 是本地自己创建的,名字取决于我们自己定义
  • --port 3000:指定服务运行在3000端口,和前端请求地址保持一致。

4.2 补充data.json模拟数据源

同目录新建data.json,接口http://localhost:3000/friends自动读取friends数据:

json 复制代码
{
  "friends": [
    {"id":1,"name":"张三","age":22},
    {"id":2,"name":"李四","age":24},
    {"id":3,"name":"王五","age":21}
  ]
}

五、前端页面+业务JS完整实战代码

5.1 HTML页面结构(index.html)

搭建基础页面骨架,包含表格容器,JS动态向tbody插入数据,代码可直接新建html文件使用。

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>前端HTTP请求实战</title>
</head>
<body>
  <header>
    <h1>前端发送http 请求渲染表格</h1>
  </header>
  <main>
    <!-- 表格容器,tbody用来动态插入行 -->
    <table border="1" cellpadding="6">
      <thead>
        <tr>
          <th>id</th>
          <th>name</th>
          <th>age</th>
        </tr>
      </thead>
      <tbody></tbody>
    </table>
  </main>
  <footer>
    <!-- 引入业务脚本 -->
    <script src="./main.js"></script>
  </footer>
</body>
</html>

5.2 main.js 核心业务逻辑

功能拆分:数据请求函数loadData、页面渲染函数renderData、项目初始化init;两种fetch写法(async/await、原生.then链式)全部注释展示。

js 复制代码
// 全局变量:存储接口返回的好友数据
let friends = [];

/**
 * @description 请求后端接口获取friends列表数据
 * @returns {Promise<Array>} 接口返回的数组数据
 */
async function loadData() {
    // endpoint:接口请求终点URL
    const endpoint = "http://localhost:3000/friends";
    // await阻塞等待fetch发送请求,拿到服务端原始响应对象
    const res = await fetch(endpoint);
    // await等待二进制响应体解析为JS对象
    const data = await res.json();// 得到friends.json 的数据
    friends = data; // 赋值给全局数据
    console.log("接口返回原始数据:", data);
    return data;

    // ========== 补充:原生Promise链式写法(不使用async/await)==========
    // fetch(endpoint)
    // .then(res => res.json())
    // .then(data => {
    //     console.log(data);
    // })
}

/**
 * @description 根据数据渲染表格DOM
 * @param {Array} friendsArr 好友数组数据
 */
function renderData(friendsArr) {
    console.log('开始执行页面渲染');
    // 获取表格tbodyDOM元素
    const oBody = document.querySelector('table tbody');
    // 数据非空才进行渲染
    if(friendsArr.length > 0){
        // map遍历数组,生成tr字符串数组,join拼接成完整html
        oBody.innerHTML = friendsArr.map(function(friend){
            return `
            <tr>
                <td>${friend.id}</td>
                <td>${friend.name}</td>
                <td>${friend.age}</td>
            </tr>
            `
        }).join('');// .join('') 把数组转为字符串
    }
}

/**
 * @description 项目初始化入口函数
 */
async function init() {
    console.log("项目初始化开始");
    // 1. 等待接口数据请求完成
    await loadData();
    // 2. 拿到数据后执行页面渲染
    renderData(friends);
}
// 启动项目
init();

5.3 项目启动步骤

  1. 终端进入项目目录,执行pnpm i json-server安装json-server依赖;
  2. 执行npx json-server data.json启动本地3000端口服务;
  3. 直接打开index.html文件,页面自动请求接口并渲染表格数据。

六、LLM接口调用方式

原生Fetch直接请求LLM HTTP接口

不引入SDK,原生fetch携带请求头、请求体,直接请求官方Endpoint,灵活可控:

js 复制代码
// url + method + http 版本号 请求行 
const endpoint =
    'https://api.deepseek.com/chat/completions';
// headers 请求头
const headers = {
    'Content-Type': 'application/json',
    // api key 通过 Authorization带上
    Authorization: `Bearer sk-783c7027777f44bfa4d2f67507acec99`
}

// 请求体
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,
        // http 请求里面 传输的不可以是对象 
        // 只能传输字符串
        body: JSON.stringify(payload)
    })
    const data = await response.json();
    console.log(data);
    document.getElementById('replay').innerHTML =
        data.choices[0].message.content;
} catch (err) {

}

七、全文总结&知识点复盘&避坑指南


全文总结

  1. 前端HTTP请求两大原生API:XMLHttpRequest(老式AJAX)、fetch(现代首选,对接LLM主流),基于前后端分离B/S架构完成前后端数据交互;
  2. 网络通信基础:IP定位服务器、端口区分应用、DNS把域名转为IP、Endpoint是接口唯一请求地址;
  3. async/await是异步请求核心语法,依托Promise改造,把异步请求同步化,简化LLM/业务接口代码;
  4. 项目落地:json-server快速搭建Mock后端,前端fetch拉取JSON数组,map拼接HTML字符串渲染页面,完整复刻真实LLM接口对接流程;
  5. LLM接口调用:原生fetch手动组装参数调用。

核心知识点复盘

  1. 架构分类:B/S浏览器服务端、C/S客户端服务端,前后端分离是接口交互标准模式;
  2. 网络基础:IP+端口定位服务,DNS解析域名→IP,Endpoint=接口URL;
  3. 异步重点 :fetch基于Promise,await等待请求和JSON解析,代码顺序执行;
  4. 数据渲染 :后端返回JSON数组 → Array.map生成HTML字符串 → innerHTML插入DOM;
  5. LLM调用:原生fetch直接请求HTTP接口。

常见问题&避坑指南

  1. ❌ 接口请求地址端口错误:前端URL端口和json-server启动端口不一致,出现跨域/请求失败;
  2. ❌ 忘记await res.json():fetch拿到的是原始响应对象,直接打印拿不到业务数据,必须解析json;
  3. ❌ map后忘记.join(''):map返回数组,直接赋值innerHTML会出现逗号分隔符,页面错乱;
  4. ❌ LLM接口缺少请求头:POST请求大模型接口必须携带Authorization密钥头、Content-Type,否则鉴权失败;
  5. ❌ 同步代码顺序误区:去掉await后,renderData优先执行,此时接口数据还未返回,表格渲染为空。
相关推荐
薛先生_0991 小时前
vue-编程式跳转-基本跳转
前端·javascript·vue.js
雪的季节1 小时前
HTTP 和 HTTPS 五大核心区别
数据库·http·https
微三云、小叶1 小时前
排队免单系统底层设计:四种分配算法拆解,无预支资金的合规营销架构方案
java·前端·软件开发·商业模式·本地生活·商业思维
copyer_xyf2 小时前
Python 内存分析:从栈和堆理解对象引用
前端·后端·python
whatever who cares2 小时前
大型 React 项目的文件结构
前端·react.js·前端框架
AI_零食2 小时前
健身室器材管理系统鸿蒙PC Electron框架编写深度解析
前端·javascript·学习·华为·electron·前端框架·鸿蒙
ZC跨境爬虫2 小时前
跟着 MDN 学 JavaScript day_2:JavaScript 初体验
开发语言·前端·javascript·学习·ecmascript
假如让我当三天老蒯2 小时前
useCallback 详细解释(从原理到用法)(自学用)
前端·react.js