Fetch API

什么是异步请求?

异步请求的定义:

浏览器使用 JavaScript,在不刷新页面的前提下,主动向服务器发送 HTTP 请求,然后根据返回的数据 动态更新页面内容

它本质上是两个部分:

  • 请求数据:fetch() 发送 HTTP 请求(GET、POST 等)
  • 处理响应:拿到服务器返回的数据(JSON、文本、文件等)后做处理

为什么不能只用 form 表单?

1. 页面刷新问题

  • 传统表单提交:提交表单时,默认会导致整个页面刷新。这种行为会影响用户体验,尤其是在单页面应用(SPA)中,用户希望在不刷新页面的情况下加载或提交数据。
  • 异步请求:通过 AJAX 或 Fetch API,可以在不重新加载页面的情况下提交数据,这样可以提供更流畅的用户体验。

2. 错误处理和反馈

  • 传统表单:处理表单验证和错误时,您需要在服务器端进行验证,返回响应后再重定向到结果页面,用户可能会迷失在过程之中。
  • 异步请求:可以立即在前端处理验证,在用户提交表单后,即使是输入错误也可以迅速给予反馈,而无需重新加载页面。

3. 动态加载和数据交互

  • 传统表单:对于需要动态交互和数据更新的场景(如选项互相依赖的下拉框),使用标准表单提交可能会很不方便。
  • 异步请求:可以在前端动态更新页面,例如根据用户输入实时更新下拉框内容,无需刷新页面。

4. 更好的用户体验

  • 动态界面:在现代 Web 应用中,许多功能要求快速的无缝体验(如即时搜索、表单自动填充等)。通过异步请求,可以在用户交互的同时更新界面,增强用户体验。
  • 部分更新:在异步请求中,您可以只更新页面的某个部分,而不影响其他部分。这种灵活性是传统表单提交所不具备的。

5. 前后端分离架构

  • API导向:在现代 Web 开发中,尤其是使用前后端分离架构(例如 React、Vue、Angular 等)时,前端与后端通常通过 API 进行交互。使用标准的表单提交与 API 不一致,因此异步请求是更常见的选择。

示例比较

传统表单提交的简单示例

<form action="/submit" method="POST">
    <input type="text" name="username" required>
    <button type="submit">提交</button>
</form>

用户提交后,页面将被重定向到 /submit 页面,表现为刷新的效果。

异步提交的示例

<form id="ajaxForm">
    <input type="text" name="username" required>
    <button type="submit">提交</button>
</form>

<script>
    document.getElementById('ajaxForm').addEventListener('submit', async (event) => {
        event.preventDefault(); // 防止默认提交
        const formData = new FormData(event.target);

        const response = await fetch('/submit', {
            method: 'POST',
            body: formData
        });

        const result = await response.json();
        console.log(result); // 处理返回的结果而不刷新页面
    });
</script>

这里,表单数据通过 JavaScript 被异步提交,页面不会刷新,用户可以继续与其他部分进行交互,同时更新反馈信息。

Fetch API 基础语法

fetch(url, options)
    .then(response => {
        // 检查响应的状态
        if (!response.ok) {
            throw new Error('Network response was not ok ' + response.statusText);
        }
        return response.json(); // 解析 JSON 数据
    })
    .then(data => {
        // 处理返回的数据
        console.log(data);
    })
    .catch(error => {
        // 处理错误
        console.error('Fetch error:', error);
    });

处理响应类型

类型方法场景
JSONres.json()后端返回结构化数据
文本res.text()返回纯文本消息
文件res.blob()下载文件、图片
fetch('/api/info')
  .then(res => {
    if (!res.ok) throw new Error('请求失败')
    return res.json()
  })
  .then(data => console.log(data))
  .catch(err => console.error(err));
  • url:要请求的资源的 URL。
  • options:可选,可以指定方法(GET、POST、PUT、DELETE等)、头信息、请求体等。

GET 请求

js:

以下示例展示如何使用 Fetch API 发送 GET 请求,并提取用户数据:

fetch('https://jsonplaceholder.typicode.com/users')
    .then(response => {
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        return response.json(); // 解析 JSON 数据
    })
    .then(users => {
        // 处理返回的用户数据
        users.forEach(user => {
            console.log(`姓名: ${user.name}, 电子邮件: ${user.email}`);
        });
    })
    .catch(error => {
        console.error('Fetch error:', error);
    });

POST 请求(发送 JSON 格式)

以下示例展示如何使用 Fetch API 发送 POST 请求以添加用户数据:

js:

const newUser = {
    name: "Alice",
    email: "alice@example.com"
};

fetch('https://jsonplaceholder.typicode.com/users', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json', // 指定请求体格式为 JSON
    },
    body: JSON.stringify(newUser) // 将 JavaScript 对象转换为 JSON 字符串
})
.then(response => {
    if (!response.ok) {
        throw new Error('Network response was not ok');
    }
    return response.json(); // 解析 JSON 数据
})
.then(data => {
    // 处理返回的数据
    console.log('新用户添加成功:', data);
})
.catch(error => {
    console.error('Fetch error:', error);
});

使用 Fetch API 的注意事项

  1. Promise 处理:Fetch API 返回一个 Promise,这意味着您可以使用 then() 和 catch() 方法链式处理成功与错误。
  2. 状态检查:使用 response.ok 属性检查响应的状态,只有状态码在 200 到 299 范围内时才标记为成功。
  3. 默认不抛出错误:如果请求失败(如 404、500),Fetch API 不会抛出错误,除非您显式进行状态检查。
  4. 跨域请求:Fetch API 需要处理 CORS(跨源资源共享)情况。如果后端没有正确设置 CORS,您可能会收到跨域限制的错误。
  5. 使用 async/await:可以结合 async/await 语法使代码更加简洁。

async/await(进阶写法)

异步函数的现代写法:

async function loadData() {
  try {
    const res = await fetch('/data');
    if (!res.ok) throw new Error('状态码异常');
    const data = await res.json();
    console.log(data);
  } catch (err) {
    console.error('出错了', err);
  }
}

demo:

async function fetchUsers() {
    try {
        let response = await fetch('https://jsonplaceholder.typicode.com/users');
        if (!response.ok) {
            throw new Error('Network response was not ok');
        }
        let users = await response.json();
        users.forEach(user => {
            console.log(`姓名: ${user.name}, 电子邮件: ${user.email}`);
        });
    } catch (error) {
        console.error('Fetch error:', error);
    }
}

fetchUsers();

await 关键字会暂停 fetchData 函数的执行,直到 fetch 请求的 Promise 被解决(即请求完成)。但请注意,这并不会阻塞整个程序的执行,其他代码依然可以运行,异步 请求的结果会在完成后被处理。

FromData表单数据处理

FormData 是一个用于构造表单数据的 JavaScript 对象,通常用于在客户端以异步方式(例如通过 Fetch API 或 XMLHttpRequest)提交包含文件的表单。它提供了一种方便的方式来构建请求的 body,支持多种类型的数据(包括文本、文件等)。下面将详细介绍 FormData 的用法及其在不同场景下的处理。

1. 创建 FormData 对象

您可以通过传递 <form> 元素或通过构造函数来创建 FormData 对象。

示例 1: 从 <form> 元素创建

<form id="myForm">
    <input type="text" name="username" required>
    <input type="file" name="file" required>
    <button type="submit">提交</button>
</form>

<script>
    const form = document.getElementById('myForm');
    const formData = new FormData(form); // 直接从表单创建 FormData 对象
</script>

示例 2: 使用构造函数创建

const formData = new FormData(); // 创建一个空的 FormData 对象

formData.append('username', 'Alice'); // 追加文本字段
formData.append('file', selectedFile); // 追加文件字段,selectedFile 是一个 File 对象

2. 向 FormData 中添加数据
您可以使用 append 方法向 FormData 中添加数据。append 方法可以添加多个字段,包括文本文件的上传。

formData.append('username', 'Alice'); // 添加用户名字段
formData.append('email', 'alice@example.com'); // 添加电子邮件字段
formData.append('file', fileInput.files[0]); // 添加文件字段,fileInput.files[0] 是选中的文件对象

3. 发送 FormData 的 GET/POST 请求

您可以使用 Fetch API 或 XMLHttpRequest 发送 FormData。以下是使用 Fetch API 的示例:

fetch('http://example.com/upload', {
    method: 'POST',
    body: formData // 将 FormData 作为请求体
})
.then(response => {
    if (!response.ok) {
        throw new Error('网络响应错误');
    }
    return response.json(); // 解析 JSON 数据
})
.then(data => {
    console.log(data); // 处理返回的数据
})
.catch(error => {
    console.error('Fetch error:', error); // 处理错误
});

4. 处理 FormData 在服务器端

在后端(例如 Flask)处理来自 FormData 的请求数据时,您可以直接使用 request.form 和 request.files 来访问请求中的表单数据以及文件。

Flask 示例:

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/upload', methods=['POST'])
def upload_file():
    # 处理文本字段
    username = request.form.get('username')
    
    # 处理文件上传
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['file']

    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400

    # 保存文件
    file.save(f"/path/to/save/{file.filename}")

    return jsonify({'message': '文件上传成功', 'username': username}), 200

if __name__ == '__main__':
    app.run(debug=True)

如何判断我该用哪种请求方式?

场景方法数据格式
获取数据GETURL 参数
登录 / 注册POSTJSON
提交表单POSTFormData
上传文件POSTFormData(带文件字段)

前端和后端之间的通信流程

  • 用户填写表单
  • JS 构造 fetch 请求(method、headers、body)
  • 浏览器发 HTTP 请求
  • Flask 接收并解析 request.form / request.json / request.files
  • Flask 返回 JSON 响应
  • 前端解析 res.json(),更新页面 DOM

表单异步提交完整demo

Fetch API 通过 POST 请求发送一个包含表单数据和文件的 FormData

后端 Flask API

安装 Flask

pip install Flask Flask-CORS

创建 Flask 应用(app.py)

from flask import Flask, request, jsonify
from flask_cors import CORS
import os

app = Flask(__name__)
CORS(app)

# 创建一个文件上传目录
UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return jsonify({'error': 'No file part'}), 400
    file = request.files['file']
    
    if file.filename == '':
        return jsonify({'error': 'No selected file'}), 400

    # 保存文件
    file.save(os.path.join(UPLOAD_FOLDER, file.filename))

    # 获取其他表单字段
    user_name = request.form.get('name')
    user_email = request.form.get('email')

    # 返回成功响应
    return jsonify({'message': 'File uploaded successfully', 'name': user_name, 'email': user_email}), 200

if __name__ == '__main__':
    app.run(debug=True)

HTML 和 JavaScript

index.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>异步表单提交示例</title>
</head>
<body>
    <h1>表单异步提交示例</h1>
    <form id="uploadForm">
        <label for="name">姓名:</label>
        <input type="text" id="name" name="name" required><br><br>
        
        <label for="email">电子邮件:</label>
        <input type="email" id="email" name="email" required><br><br>
        
        <label for="file">选择文件:</label>
        <input type="file" id="file" name="file" required><br><br>
        
        <button type="submit">提交</button>
    </form>

    <div id="response"></div>

    <script>
        const form = document.getElementById('uploadForm');
        const responseDiv = document.getElementById('response');

        form.addEventListener('submit', async (event) => {
            event.preventDefault(); // 阻止默认提交

            const formData = new FormData(form); // 创建 FormData 对象

            try {
                const response = await fetch('http://127.0.0.1:5000/upload', {
                    method: 'POST',
                    body: formData // 将 FormData 作为请求体
                });

                if (!response.ok) {
                    throw new Error('网络响应错误');
                }

                const result = await response.json();
                // 显示成功信息
                responseDiv.innerHTML = `<p>${result.message}</p><p>姓名: ${result.name}, 电子邮件: ${result.email}</p>`;
            } catch (error) {
                responseDiv.innerHTML = `<p>错误: ${error.message}</p>`;
            }
        });
    </script>
</body>
</html>

运行和测试

1、启动 Flask 服务器:
在终端中导航到包含 app.py 的目录,然后运行:
python app.py
Flask 应该会在 http://127.0.0.1:5000/ 地址运行。

2、打开 HTML 文件:
进入到包含 index.html 的目录,然后 python -m http.server 8000
(使用 python -m http.server 8000 启动一个本地的 HTTP 服务器可以让您在开发和测试阶段轻松地提供静态文件,并避免潜在的 CORS 问题)

3、测试表单:
在浏览器中访问 http://localhost:8000/index.html。
填写表单中的姓名和电子邮件。
选择一个文件进行上传。
点击“提交”按钮,您应该能够看到文件上传并返回的成功消息。
Fetch API

发布者:LJH,转发请注明出处:https://www.ljh.cool/42784.html

Like (0)
LJHLJH
Previous 6天前
Next 2020年10月30日 下午2:40

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注