睿诚科技协会

JavaScript 网络编程如何实现前后端数据交互?

分为以下几个部分,由浅入深:

JavaScript 网络编程如何实现前后端数据交互?-图1
(图片来源网络,侵删)
  1. 核心基础:fetch API - 现代、强大、推荐使用的网络请求方式。
  2. 经典方案:XMLHttpRequest (XHR) - 老牌方案,理解它有助于阅读旧代码。
  3. 现代应用:WebSocket - 实现全双工、低延迟的实时通信。
  4. 高级应用:Server-Sent Events (SSE) - 服务器向客户端单向推送数据。
  5. 最佳实践与常见问题 - 包括错误处理、跨域、安全等。

核心基础:fetch API

fetch 是现代浏览器提供的、基于 Promise 的网络请求 API,是替代 XMLHttpRequest 的首选,它语法更简洁,功能更强大。

基本语法

fetch(url, options) 返回一个 Promise,该 Promise 解析为一个 Response 对象。

// GET 请求示例
fetch('https://api.example.com/data')
  .then(response => {
    // response 对象包含响应头、状态码等,但响应体本身需要进一步解析
    // 首先检查是否成功 (HTTP 状态码 200-299)
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    // 将响应体解析为 JSON
    return response.json(); // response.json() 也是一个 Promise
  })
  .then(data => {
    console.log('获取到的数据:', data);
    // 在这里处理数据
  })
  .catch(error => {
    // 捕获网络错误或上面的 throw new Error
    console.error('请求失败:', error);
  });

POST 请求示例

POST 请求需要在 options 对象中指定 methodheadersbody

const postData = {
  name: 'John Doe',
  email: 'john.doe@example.com'
};
fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json', // 告诉服务器我们发送的是 JSON
  },
  body: JSON.stringify(postData) // 将 JavaScript 对象转换为 JSON 字符串
})
.then(response => response.json())
.then(data => {
  console.log('服务器响应:', data);
})
.catch(error => {
  console.error('请求失败:', error);
});

fetch 的优点:

JavaScript 网络编程如何实现前后端数据交互?-图2
(图片来源网络,侵删)
  • 基于 Promise,避免了回调地狱。
  • 语法更简洁、更现代化。
  • 提供了对请求和响应流的更好控制。

经典方案:XMLHttpRequest (XHR)

XMLHttpRequest 是一个老牌的 API,在 fetch 出现之前是进行异步网络请求的唯一标准,现在很多旧项目仍在使用它。

基本用法

它通过创建一个 XMLHttpRequest 对象,然后配置和发送请求。

// 1. 创建 XHR 对象
const xhr = new XMLHttpRequest();
// 2. 配置请求
// method: GET/POST/PUT/DELETE
// url: 请求的地址
// true: 表示异步请求
xhr.open('GET', 'https://api.example.com/data', true);
// 3. 设置回调函数
// 当请求状态发生变化时触发
xhr.onreadystatechange = function() {
  // readyState 4 表示请求已完成
  // status 200 表示请求成功
  if (xhr.readyState === 4 && xhr.status === 200) {
    // responseText 是服务器返回的原始文本
    console.log('获取到的数据:', xhr.responseText);
    // 通常需要手动解析 JSON
    const data = JSON.parse(xhr.responseText);
    console.log('解析后的数据:', data);
  } else if (xhr.readyState === 4) {
    // 请求完成但失败了
    console.error('请求失败,状态码:', xhr.status);
  }
};
// 4. 发送请求
// 对于 GET 请求,send() 为空或 null
// 对于 POST 请求,send() 里面放请求体
xhr.send();

XMLHttpRequest 的缺点:

  • 基于回调,容易形成回调地狱。
  • 语法相对繁琐。
  • 不如 fetch 灵活。

现代应用:WebSocket

fetchXHR 都是 HTTP 协议的请求-响应模式(客户端问,服务器答),而 WebSocket 是一种全双工通信协议,允许服务器和客户端之间建立一个持久连接,实现服务器主动向客户端推送数据,非常适合实时场景(如聊天室、在线游戏、股票行情等)。

JavaScript 网络编程如何实现前后端数据交互?-图3
(图片来源网络,侵删)

基本用法

// 1. 创建 WebSocket 连接
// ws:// 是 WebSocket 协议,wss:// 是加密的 WebSocket 协议
const socket = new WebSocket('wss://echo.websocket.org'); // 这是一个测试服务器,会回显你发送的消息
// 2. 监听事件
socket.onopen = function(event) {
  console.log('WebSocket 连接已建立!');
  // 连接成功后,可以发送数据
  socket.send('Hello, Server!');
};
socket.onmessage = function(event) {
  // event.data 是服务器发来的数据
  console.log('收到服务器消息:', event.data);
};
socket.onclose = function(event) {
  if (event.wasClean) {
    console.log(`连接正常关闭,代码=${event.code} 原因=${event.reason}`);
  } else {
    // 服务器进程被杀死或网络中断
    console.error('连接异常关闭');
  }
};
socket.onerror = function(error) {
  console.error('WebSocket 发生错误:', error);
};
// 3. 手动关闭连接
// socket.close();

高级应用:Server-Sent Events (SSE)

SSE 是一种服务器向客户端单向推送数据的技术,它基于 HTTP 协议,比 WebSocket 更简单,适用于服务器向客户端实时更新场景(如新闻推送、日志更新)。

客户端使用 EventSource 对象来接收服务器事件。

客户端代码

// 1. 创建 EventSource 对象
// URL 必须支持 CORS
const eventSource = new EventSource('https://api.example.com/updates');
// 2. 监听消息
eventSource.onmessage = function(event) {
  // event.data 是服务器推送的数据
  console.log('收到更新:', event.data);
};
// 3. 监听自定义事件
// 服务器可以发送不同类型的事件,客户端可以分别监听
eventSource.addEventListener('news', function(event) {
  console.log('新闻更新:', event.data);
});
eventSource.addEventListener('like', function(event) {
  console.log('收到点赞:', event.data);
});
// 4. 监听错误
eventSource.onerror = function(err) {
  console.error('SSE 发生错误:', err);
  // 连接断开后,浏览器会自动尝试重新连接
  // 如果不想重连,可以关闭
  // eventSource.close();
};

服务器端代码 (Node.js 示例)

服务器需要设置正确的 Content-Type 头,并持续发送数据。

const http = require('http');
const server = http.createServer((req, res) => {
  if (req.url === '/updates') {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream', // 关键头
      'Cache-Control': 'no-cache',
      'Connection': 'keep-alive',
    });
    // 模拟定时推送数据
    const intervalId = setInterval(() => {
      const data = { time: new Date().toISOString() };
      // 格式: data: <内容>\n\n
      res.write(`data: ${JSON.stringify(data)}\n\n`);
    }, 1000);
    // 当客户端断开连接时,清除定时器
    req.on('close', () => {
      clearInterval(intervalId);
      res.end();
    });
  } else {
    res.writeHead(404);
    res.end();
  }
});
server.listen(3000, () => {
  console.log('SSE 服务器运行在 http://localhost:3000');
});

最佳实践与常见问题

错误处理

  • fetch: catch 会捕获网络错误(如断网),但不会捕获 HTTP 状态码错误(如 404, 500),必须检查 response.okresponse.status
  • XHR: 需要检查 xhr.statusxhr.readyState
  • WebSocket: 通过 onerror 事件处理。

跨域资源共享

出于安全考虑,浏览器会阻止网页向不同源(不同域名、协议或端口)的 API 发起请求,这被称为同源策略

解决方案是 CORS (Cross-Origin Resource Sharing)

  1. 服务器端配置:服务器需要在响应头中添加 Access-Control-Allow-Origin
    • Access-Control-Allow-Origin: *
分享:
扫描分享到社交APP
上一篇
下一篇