前端异步请求踩坑?3种方式搞定Ajax数据交互,从XHR到async/await
2026/6/16 21:57:21 网站建设 项目流程

作为前端开发者,你是不是也遇到过这些问题:

  • 想在页面不刷新的情况下获取后端数据,却不知道怎么下手?
  • 用XHR写Ajax请求,回调嵌套绕到晕?
  • 异步代码执行顺序混乱,console.log先出end再出数据?

这篇文章我会用实战案例,从基础的XHR到现代的async/await,手把手教你3种前端异步请求方式,彻底搞懂JS异步逻辑,搞定前后端数据交互!

一、先搞懂:为什么需要Ajax?

在Web2.0时代,我们要实现页面不刷新就能动态更新内容(比如待办列表、商品数据),就必须用Ajax发起HTTP请求。

核心逻辑:

  • JS是单线程语言,遇到异步任务不会阻塞,会丢到eventloop队列
  • 等异步任务执行时机到了,eventloop再把任务放回JS线程执行
  • Ajax就是最典型的异步场景,核心是「后台请求数据+前端动态渲染」

二、实战场景:搭建本地接口+前端请求渲染待办列表

先搭一个极简的本地Node服务,提供待办列表接口,再用不同方式请求数据渲染页面,全程代码可直接复制运行!

第一步:搭建本地Node服务(提供/todos接口)

新建index.js文件,复制以下代码:

// 引入Node内置http模块consthttp=require("http");// 创建HTTP服务http.createServer((req,res)=>{// 模拟待办列表数据consttodos=[{id:"1",title:"过四六级",completed:false},{id:"2",title:"回家过节",completed:false}];// 🔥 踩坑提醒:跨域必加!否则前端请求会报错res.setHeader("Access-Control-Allow-Origin","*");// 告诉前端响应数据是JSON格式res.setHeader("Content-Type","application/json; charset=utf-8");// 接口路由处理if(req.url==="/"){res.end("hello world");}if(req.url==="/todos"){// 把对象序列化为JSON字符串(网络传输必须转字符串)res.end(JSON.stringify(todos));}}).listen(3000,()=>{console.log("server is running at 3000 port");});

运行命令:

nodeindex.js

此时访问http://localhost:3000/todos,就能看到JSON格式的待办数据,接口搭建完成!

第二步:前端页面准备(基础结构)

新建index.html文件,基础结构如下:

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>Ajax实战</title></head><body><!-- 待办列表容器 --><ulclass="todo-list"></ul><script>// 后续请求代码写在这里</script></body></html>

三、3种Ajax请求方式,从旧到新逐个讲

方式1:传统XHR(XMLHttpRequest)—— 基础但繁琐

这是Ajax的「老前辈」,虽然写法繁琐,但理解它能搞懂异步本质!

把以下代码替换到index.html的script标签中:

// 1. 实例化XHR对象constxhr=newXMLHttpRequest();// 2. 打开通信通道:GET请求 + 接口地址 + 是否异步(true=异步)xhr.open("GET","http://localhost:3000/todos",true);console.log("start");// 3. 监听状态变化(回调函数)xhr.onreadystatechange=function(){// 🔥 踩坑提醒:必须判断状态码,否则会多次触发if(xhr.readyState===4&&xhr.status===200){// 把JSON字符串解析为JS对象consttodos=JSON.parse(xhr.responseText);console.log(todos);// 渲染到页面document.querySelector(".todo-list").innerHTML=todos.map(todo=>`<li>${todo.title}</li>`).join("");}};// 4. 发送请求xhr.send();console.log("end");
运行结果&踩坑点:
  • console先输出startend,再输出todos数据(异步特性)
  • 必踩坑:忘记判断readyState === 4status === 200,会导致代码多次执行
  • 缺点:回调嵌套多了会形成「回调地狱」,代码可读性差

方式2:Promise封装(fetch)—— 简化回调

fetch是基于Promise的新一代请求方式,写法更简洁,无需手动监听状态!

替换script标签代码:

console.log("start");// fetch返回Promise对象,用then处理异步结果fetch("http://localhost:3000/todos")// 第一步:解析响应为JSON.then(res=>res.json())// 第二步:渲染数据.then(todos=>{console.log(todos);document.querySelector(".todo-list").innerHTML=todos.map(todo=>`<li>${todo.title}</li>`).join("");})// 🔥 踩坑提醒:fetch仅捕获网络错误,HTTP错误(如404)需手动判断.catch(err=>console.error("请求失败:",err));console.log("end");
优点&踩坑点:
  • 优点:链式调用替代回调嵌套,代码更清晰
  • 踩坑点:fetch不会自动拦截404/500等HTTP错误,需在第一个then里判断res.ok

方式3:async/await —— 异步代码「同步化」(推荐)

这是目前最优雅的写法,基于Promise封装,代码和同步逻辑几乎一致,可读性拉满!

替换script标签代码:

// 封装为async函数asyncfunctiongetTodos(){try{console.log("start");// 等待请求响应constres=awaitfetch("http://localhost:3000/todos");// 🔥 踩坑提醒:手动判断响应状态if(!res.ok){thrownewError(`HTTP错误:${res.status}`);}// 等待解析JSONconsttodos=awaitres.json();// 渲染数据document.querySelector(".todo-list").innerHTML=todos.map(todo=>`<li>${todo.title}</li>`).join("");console.log(todos);console.log("end");}catch(err){console.error("请求失败:",err);}}// 执行函数getTodos();
核心优势:
  • 代码线性执行,和同步代码逻辑一致,新手也能看懂
  • try/catch统一捕获错误,无需在then里单独处理
  • 是目前前端异步请求的「最优解」,大厂项目几乎都用它

四、关键知识点补充(必记)

1. JSON.stringify/JSON.parse

  • JSON.stringify(obj):把JS对象转为JSON字符串(网络传输必须用字符串)
  • JSON.parse(str):把JSON字符串转回JS对象
  • 可选参数:JSON.stringify(value, replace, space)
    • replace:筛选/修改序列化的属性(null=原样序列化)
    • space:设置空格数,提升可读性(团队规范常用2/4个空格)

2. 异步执行核心逻辑

  • JS单线程 → 异步任务入eventloop队列 → 主线程空闲后执行
  • await会「暂停」async函数执行,等待Promise完成后再继续
  • 异步代码执行顺序:同步代码先执行,异步代码后执行(比如前面的start/end输出顺序)

五、总结

今天我们用「待办列表」实战场景,讲了3种Ajax请求方式:

  1. XHR:基础底层,理解异步本质,但写法繁琐
  2. fetch+Promise:简化回调,链式调用更清晰
  3. async/await:异步代码同步化,可读性最高,推荐生产环境使用

核心收获:

  • 搞定前后端跨域(设置Access-Control-Allow-Origin)
  • 掌握异步代码执行逻辑,避免顺序混乱
  • 能独立搭建本地接口+前端请求渲染页面

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

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

立即咨询