JavaScript:网络请求与前端通信

第十阶段:网络请求与前端通信

  1. XMLHttpRequest(简称 XHR)原生 AJAX:

    AJAX :Asynchronous JavaScript And XML

    异步 JS 和 XML,作用:不刷新整个页面,局部更新数据。

    现在主流传输格式是 JSON,XML 基本淘汰。

同步 / 异步请求、请求状态码 status、readyState:

  • 同步请求:请求会阻塞代码执行,直到请求完成。例如:
js 复制代码
let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/api', false);
xhr.send();
if (xhr.status === 200) {
    console.log(xhr.responseText);
}
  • 异步请求 :请求不会阻塞代码执行,通过监听 readystatechange 事件获取请求状态。例如:
js 复制代码
let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://example.com/api', true);
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
};
xhr.send();
  • 请求状态码 status :表示请求的结果,如 200 表示成功,404 表示未找到资源等。
  • readyState :表示请求的阶段,0 为未初始化,1 为已调用 open 方法,2 为已调用 send 方法,3 为请求中,4 为请求完成。

GET/POST 请求、请求头、请求参数、上传文件:

  • GET 请求:将参数附加在 URL 后面。例如:
js 复制代码
let xhr = new XMLHttpRequest();
let params = 'param1=value1&param2=value2';
xhr.open('GET', 'https://example.com/api?' + params, true);
xhr.send();
  • POST 请求:将参数放在请求体中。例如:
js 复制代码
let xhr = new XMLHttpRequest();
let params = 'param1=value1&param2=value2';
xhr.open('POST', 'https://example.com/api', true);
xhr.setRequestHeader('Content- type', 'application/x- www- form- urlencoded');
xhr.send(params);
  • 请求头 :使用 setRequestHeader 方法设置。例如设置 Content- type 头:
js 复制代码
xhr.setRequestHeader('Content- type', 'application/json');
  • 上传文件 :使用 FormData 对象。例如:
html 复制代码
<input type="file" id="fileInput">
<button id="uploadButton">上传</button>
<script>
    let uploadButton = document.getElementById('uploadButton');
    let fileInput = document.getElementById('fileInput');
    uploadButton.addEventListener('click', function () {
        let xhr = new XMLHttpRequest();
        let formData = new FormData();
        formData.append('file', fileInput.files[0]);
        xhr.open('POST', 'https://example.com/upload', true);
        xhr.send(formData);
    });
</script>
  1. Fetch API「ES6+」:

fetch 基础语法、Request/Response 对象:

  • 基础语法 :fetch 返回一个 Promise。例如:
js 复制代码
fetch('https://example.com/api')
  .then(response => response.json())
  .then(data => console.log(data));
  • Request 对象:可用于创建自定义请求。例如:
js 复制代码
let request = new Request('https://example.com/api', {
    method: 'GET',
    headers: {
        'Content- type': 'application/json'
    }
});
fetch(request)
  .then(response => response.json())
  .then(data => console.log(data));
  • Response 对象 :包含请求的响应。response.json() 用于解析 JSON 数据,response.text() 用于获取文本数据等。

Headers、GET/POST 传参、FormData:

  • Headers :可通过 headers 属性操作响应头。例如:
js 复制代码
fetch('https://example.com/api')
  .then(response => {
        console.log(response.headers.get('Content- type'));
        return response.json();
    })
  .then(data => console.log(data));
  • GET 传参:将参数拼接到 URL 上。例如:
js 复制代码
let params = new URLSearchParams();
params.append('param1', 'value1');
fetch('https://example.com/api?' + params.toString())
  .then(response => response.json())
  .then(data => console.log(data));
  • POST 传参 :使用 body 属性设置请求体。例如:
js 复制代码
let data = { key: 'value' };
fetch('https://example.com/api', {
    method: 'POST',
    headers: {
        'Content- type': 'application/json'
    },
    body: JSON.stringify(data)
})
  .then(response => response.json())
  .then(data => console.log(data));
  • FormData:用于上传文件和表单数据。例如:
html 复制代码
<input type="file" id="fileInput">
<button id="uploadButton">上传</button>
<script>
    let uploadButton = document.getElementById('uploadButton');
    let fileInput = document.getElementById('fileInput');
    uploadButton.addEventListener('click', function () {
        let formData = new FormData();
        formData.append('file', fileInput.files[0]);
        fetch('https://example.com/upload', {
            method: 'POST',
            body: formData
        })
          .then(response => response.text())
          .then(data => console.log(data));
    });
</script>

fetch 坑:4xx/5xx 不会触发 reject、跨域处理:

  • 4xx/5xx 不会触发 reject :fetch 只有在网络错误或请求被阻止时才会 reject,4xx 和 5xx 状态码不会。需要手动检查 response.ok。例如:
js 复制代码
fetch('https://example.com/api')
  .then(response => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        return response.json();
    })
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error));
  • 跨域处理 :与 XMLHttpRequest 类似,通常通过 CORS 解决。服务端设置允许的源等响应头,前端无需特殊配置。
  1. 跨域问题详解:
  • 同源策略定义 :同源策略是浏览器的安全策略,要求协议、域名、端口都相同,否则视为跨域。例如,http://example.com:8080 和 http://example.com:8081 不同源。
  • CORS 跨域资源共享(服务端配置) :服务端通过设置响应头允许跨域。例如在 Node.js 中使用 express- cors 中间件:
js 复制代码
const express = require('express');
const cors = require('express- cors');
const app = express();
app.use(cors());
// 其他路由和处理
  • JSONP 跨域原理 :利用 <script> 标签没有跨域限制的特点。前端创建一个 <script> 标签,设置其 src 属性为跨域接口,并指定一个回调函数名。服务端返回包含该回调函数调用及数据的 JavaScript 代码。例如:
html 复制代码
<script>
    function handleResponse(data) {
        console.log(data);
    }
</script>
<script src="https://example.com/api?callback = handleResponse"></script>

代理服务器、iframe 跨域、postMessage「ES6+」:

  • 代理服务器:前端请求本地代理服务器,代理服务器再请求跨域资源,然后将响应返回给前端,避免直接跨域。
  • iframe 跨域 :通过在主页面嵌入一个与目标域同源的 iframe,主页面和 iframe 之间通过 postMessage 通信。例如:
html 复制代码
<!-- 主页面-->
<iframe id="iframe" src="http://same- origin- domain.com/iframe.html"></iframe>
<script>
    window.addEventListener('message', function (event) {
        if (event.origin === 'http://same- origin- domain.com') {
            console.log('收到来自 iframe 的消息:', event.data);
        }
    });
    document.getElementById('iframe').contentWindow.postMessage('来自主页面的消息', 'http://same- origin- domain.com');
</script>
html 复制代码
<!-- iframe.html-->
<script>
    window.addEventListener('message', function (event) {
        if (event.origin === 'http://parent- domain.com') {
            console.log('收到来自主页面的消息:', event.data);
            window.parent.postMessage('来自 iframe 的回复', 'http://parent- domain.com');
        }
    });
</script>
  • postMessage「ES6+」 :可用于窗口之间的跨域通信,如 window.postMessage(data, targetOrigin)。
  1. WebSocket「ES6+」长连接实时通信:
  • 是什么:WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,允许服务器主动向客户端推送数据。例如:
js 复制代码
let socket = new WebSocket('ws://example.com/socket');
socket.onopen = function () {
    console.log('连接已建立');
    socket.send('Hello, server!');
};
socket.onmessage = function (event) {
    console.log('收到消息:', event.data);
};
socket.onclose = function () {
    console.log('连接已关闭');
};
  • 为什么:传统的 HTTP 是请求- 响应模式,服务器不能主动推送数据。WebSocket 适用于实时通信场景,如聊天应用、实时数据更新等。
  • 怎么用 :创建 WebSocket 实例,监听 open(连接建立)、message(收到消息)、close(连接关闭)等事件,使用 send 方法发送数据。
  1. 简单文件上传、下载前端实现:
  • 文件上传 :已在 XMLHttpRequest 和 Fetch API 部分介绍,通过 FormData 对象实现。
  • 文件下载 :可以创建一个 <a> 标签,设置其 href 属性为文件的 URL,并设置 download 属性指定下载文件名。例如:
html 复制代码
<button id="downloadButton">下载文件</button>
<script>
    let downloadButton = document.getElementById('downloadButton');
    downloadButton.addEventListener('click', function () {
        let a = document.createElement('a');
        a.href = 'https://example.com/file.pdf';
        a.download = 'example.pdf';
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    });
</script>

实战练习:

  1. fetch 发送表单 FormData 上传数据
  2. JSONP 简易跨域封装
  3. WebSocket 简易聊天室收发消息

思考题:

  1. fetch 为什么 4xx/5xx 不会进入 catch?
  2. 同源策略限制哪些操作?
  3. WebSocket 和 AJAX 轮询区别?
相关推荐
AKA__Zas6 小时前
TCP 与 IP 浅显皮毛
服务器·网络·tcp/ip
tachibana27 小时前
与其他语言相比,使用 Go 有什么好处?
开发语言·后端·golang·go
阿俊-全栈开发11 小时前
LikeShop 单商户SaaS商城分销模块二开:佣金计算与结算逻辑实现
java·开发语言·微服务·likeshop·likeshop开源商城·likeshop多商户
奕鼎竜瑆13 小时前
Solid 前端响应式开发从零到精通
前端·人工智能
源流之道14 小时前
联想Y700 五代(TB323FU)刷 ColorOS 16 教程指南
网络·ai·刷机指南·刷机心得
GEO从入门到精通14 小时前
课程怎么选?2026年GEO学习资源全梳理
学习
动恰客流统计14 小时前
景区客流统计怎么做?兼顾管控与运营的实施方案解析
大数据·前端·人工智能
优化Henry15 小时前
LTE 载波频率与频点配置详解
运维·网络·学习·5g·信息与通信
派小心.15 小时前
A/B测试工具免费版够用吗?
前端·数据分析
m0_3807438715 小时前
C++中的freopen的用法实例详解
开发语言·c++