author: 专注前端开发,分享JavaScript干货
title: JavaScript入门⑨|Fetch与AJAX,浏览器网络请求一篇搞懂
update: 2026-04-28
tags: JavaScript,Fetch,AJAX,网络请求,API,JSON,前端入门,HTTP

作者:专注前端开发,分享JavaScript干货
更新时间:2026年4月
适合人群:掌握异步编程,想发起真实网络请求的同学


前言:AJAX与Fetch

网页要获取服务器数据(登录、加载列表、上传文件),全靠网络请求

这一篇搞定浏览器端发起网络请求的所有方式。


一、XMLHttpRequest(XHR)

老式但仍广泛使用的方式:

const xhr = new XMLHttpRequest();
xhr.open("GET", "https://jsonplaceholder.typicode.com/users/1");
xhr.send();

xhr.onload = function() {
    if (xhr.status === 200) {
        const data = JSON.parse(xhr.responseText);
        console.log(data);
    } else {
        console.error("请求失败", xhr.status);
    }
};

xhr.onerror = function() {
    console.error("网络错误");
};

// 进度监控
xhr.upload.onprogress = function(e) {
    const percent = (e.loaded / e.total * 100).toFixed(1);
    console.log(`上传进度:${percent}%`);
};

二、Fetch API(现代方式)

2.1 GET请求

// 最简单的方式
fetch("https://jsonplaceholder.typicode.com/users/1")
    .then(response => {
        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }
        return response.json(); // 解析JSON
    })
    .then(data => console.log(data))
    .catch(error => console.error("错误:", error));

2.2 POST请求

fetch("https://jsonplaceholder.typicode.com/posts", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        // 如果要传表单数据:
        // "Content-Type": "application/x-www-form-urlencoded",
    },
    body: JSON.stringify({
        title: "我的文章",
        body: "文章内容",
        userId: 1
    })
})
    .then(response => response.json())
    .then(data => console.log("创建成功:", data));

2.3 PUT / DELETE

// PUT(更新全部)
fetch("https://jsonplaceholder.typicode.com/posts/1", {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ id: 1, title: "更新后的标题", body: "内容", userId: 1 })
}).then(r => r.json()).then(console.log);

// DELETE(删除)
fetch("https://jsonplaceholder.typicode.com/posts/1", {
    method: "DELETE"
}).then(r => console.log("删除状态:", r.status));

三、Fetch详细配置

fetch(url, {
    method: "GET",                    // GET/POST/PUT/DELETE/PATCH
    headers: {                        // 请求头
        "Content-Type": "application/json",
        "Authorization": "Bearer token123",
        "Accept": "application/json"
    },
    body: JSON.stringify(data),       // 请求体(GET/HEAD不能有body)
    mode: "cors",                     // cors/no-cors/same-origin
    credentials: "include",           // include/same-origin/omit(是否携带Cookie)
    cache: "no-cache",                // default/no-cache/reload/force-cache
    redirect: "follow",              // follow/error/manual
    referrer: "no-referrer",         // 来源策略
    signal: abortController.signal    // 可取消的请求
})

四、async/await 封装 Fetch

// 封装成更易用的函数
async function request(url, options = {}) {
    const defaultOptions = {
        headers: {
            "Content-Type": "application/json",
            ...options.headers
        }
    };

    try {
        const response = await fetch(url, { ...defaultOptions, ...options });

        if (!response.ok) {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
        }

        // 自动解析JSON(如果是JSON响应)
        const contentType = response.headers.get("content-type");
        if (contentType && contentType.includes("application/json")) {
            return await response.json();
        }
        return await response.text();

    } catch (error) {
        console.error("请求失败:", error.message);
        throw error;
    }
}

// 使用
async function getUser() {
    const user = await request("https://jsonplaceholder.typicode.com/users/1");
    console.log(user);
}

async function createPost() {
    const post = await request("https://jsonplaceholder.typicode.com/posts", {
        method: "POST",
        body: JSON.stringify({ title: "新文章", body: "内容", userId: 1 })
    });
    console.log(post);
}

五、处理各种数据格式

// 1. JSON(最常用)
const r1 = await fetch(url);
const json = await r1.json();

// 2. 纯文本
const r2 = await fetch(url);
const text = await r2.text();

// 3. Blob(文件、图片)
const r3 = await fetch("https://via.placeholder.com/300");
const blob = await r3.blob();
const img = document.createElement("img");
img.src = URL.createObjectURL(blob);
document.body.appendChild(img);

// 4. ArrayBuffer(二进制数据)
const r4 = await fetch("https://example.com/file");
const buffer = await r4.arrayBuffer();

// 5. FormData(表单/文件上传)
const formData = new FormData();
formData.append("file", fileInput.files[0]);
formData.append("name", "张三");

const r5 = await fetch("/api/upload", {
    method: "POST",
    body: formData
    // 注意:FormData会自动设置 Content-Type: multipart/form-data
});

// 6. URLSearchParams(表单编码)
const params = new URLSearchParams();
params.append("page", "1");
params.append("limit", "10");

const r6 = await fetch(`/api/list?${params}`);

六、取消请求(AbortController)

const controller = new AbortController();
const signal = controller.signal;

// 3秒后自动取消
const timeoutId = setTimeout(() => controller.abort(), 3000);

fetch(url, { signal })
    .then(r => r.json())
    .then(data => {
        clearTimeout(timeoutId);
        console.log(data);
    })
    .catch(error => {
        if (error.name === "AbortError") {
            console.log("请求被取消了");
        } else {
            console.error(error);
        }
    });

// 也可以手动取消
// controller.abort();

七、综合实战:用户列表展示

class UserService {
    constructor(baseUrl) {
        this.baseUrl = baseUrl;
    }

    async request(url, options = {}) {
        const response = await fetch(this.baseUrl + url, {
            headers: { "Content-Type": "application/json" },
            ...options
        });

        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }

        return response.json();
    }

    getUsers() {
        return this.request("/users");
    }

    getUser(id) {
        return this.request(`/users/${id}`);
    }

    createUser(data) {
        return this.request("/users", {
            method: "POST",
            body: JSON.stringify(data)
        });
    }

    updateUser(id, data) {
        return this.request(`/users/${id}`, {
            method: "PUT",
            body: JSON.stringify(data)
        });
    }

    deleteUser(id) {
        return this.request(`/users/${id}`, {
            method: "DELETE"
        });
    }
}

// 使用
const api = new UserService("https://jsonplaceholder.typicode.com");

async function main() {
    try {
        // 获取用户列表
        const users = await api.getUsers();
        console.log("用户列表:", users.slice(0, 3));

        // 获取单个用户
        const user = await api.getUser(1);
        console.log("单个用户:", user);

        // 创建用户
        const newUser = await api.createUser({
            name: "张三",
            username: "zhangsan",
            email: "zhangsan@example.com"
        });
        console.log("创建的用户:", newUser);

    } catch (error) {
        console.error("操作失败:", error.message);
    }
}

main();

八、知识卡

知识点 说明
fetch() 现代网络请求API
response.ok HTTP状态码200-299
response.json() 解析JSON响应
response.headers 访问响应头
AbortController 取消请求
FormData 表单/文件上传
Blob 二进制大对象(图片/文件)
async/await 让fetch更易用

九、课后作业

  1. 用Fetch请求一个公开API(如jsonplaceholder),展示返回数据
  2. 实现一个可取消的请求,3秒超时
  3. 实现文件上传功能:选择本地图片,上传到页面显示预览

有问题欢迎评论区留言,大家一起讨论!


标签:JavaScript | Fetch | AJAX | 网络请求 | API | JSON | HTTP | 前端入门

更多推荐