初级程序员必备的十大技能之 API 接口与前后端联调(四)

简介: 教程来源 https://ltglu.cn/ Postman、Apifox与Swagger是主流API调试与文档工具:Postman侧重灵活调试与脚本测试;Apifox国产集成强,支持文档/Mock/测试一体化;Swagger(OpenAPI)专注标准化接口定义,助力前后端契约开发与协同。

五、接口调试工具

5.1 Postman
Postman 是最流行的 API 调试工具。

常用功能:

# 1. 环境变量管理
# 设置环境变量
{
  {base_url}}/api/users

# 2. 集合(Collection)
# 将相关接口分组,可以批量运行测试

# 3. 测试脚本
pm.test("状态码为 200", function () {
    pm.response.to.have.status(200);
});

pm.test("返回数据包含用户", function () {
    var jsonData = pm.response.json();
    pm.expect(jsonData.data).to.be.an('array');
});

# 4. 前置脚本(如动态生成 token)
pm.environment.set("timestamp", Date.now());

# 5. 导入/导出
# 导出为 JSON,可以和团队共享

5.2 Apifox(国内推荐)
Apifox = Postman + Swagger + Mock + JMeter,一体化工具。

核心优势:

接口文档、调试、Mock、测试一体化

支持自动生成前端/后端代码

支持 OpenAPI(Swagger)导入导出

团队协作,实时同步

5.3 Swagger(OpenAPI)
Swagger 是最流行的 API 文档规范。

# openapi.yaml
openapi: 3.0.0
info:
  title: 用户管理 API
  version: 1.0.0
paths:
  /users/{id}:
    get:
      summary: 获取用户信息
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  id:
                    type: integer
                  name:
                    type: string
                  email:
                    type: string
// Node.js 中使用 Swagger(nestjs)
@Get(':id')
@ApiOperation({ summary: '获取用户' })
@ApiResponse({ status: 200, description: '成功', type: UserDto })
findOne(@Param('id') id: string) {
  return this.userService.findOne(+id);
}

六、前后端联调实战

6.1 完整的登录流程
后端实现(Node.js + Express)

// server/routes/auth.js
const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const router = express.Router();

// 用户登录
router.post('/login', async (req, res) => {
  const { username, password } = req.body;

  // 1. 参数校验
  if (!username || !password) {
    return res.status(400).json({
      code: 400,
      message: '用户名和密码不能为空'
    });
  }

  // 2. 查询用户
  const user = await db.findUserByUsername(username);
  if (!user) {
    return res.status(400).json({
      code: 40001,
      message: '用户不存在'
    });
  }

  // 3. 验证密码
  const isValid = await bcrypt.compare(password, user.password);
  if (!isValid) {
    return res.status(400).json({
      code: 40002,
      message: '密码错误'
    });
  }

  // 4. 生成 token
  const token = jwt.sign(
    { userId: user.id, username: user.username },
    process.env.JWT_SECRET,
    { expiresIn: '7d' }
  );

  // 5. 返回结果
  res.json({
    code: 200,
    message: '登录成功',
    data: {
      token,
      userId: user.id,
      username: user.username,
      avatar: user.avatar
    }
  });
});

// 验证 token(中间件)
const authMiddleware = (req, res, next) => {
  const token = req.headers.authorization?.replace('Bearer ', '');

  if (!token) {
    return res.status(401).json({
      code: 401,
      message: '未提供 token'
    });
  }

  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET);
    req.user = decoded;
    next();
  } catch (err) {
    return res.status(401).json({
      code: 401,
      message: 'token 无效或已过期'
    });
  }
};

// 获取当前用户信息(需要认证)
router.get('/me', authMiddleware, async (req, res) => {
  const user = await db.findUserById(req.user.userId);
  res.json({
    code: 200,
    data: {
      id: user.id,
      username: user.username,
      email: user.email
    }
  });
});

module.exports = router;

前端实现(React)

// pages/Login.jsx
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { http } from '@/utils/request';

function Login() {
  const navigate = useNavigate();
  const [formData, setFormData] = useState({
    username: '',
    password: ''
  });
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);
    setError('');

    try {
      // 发送登录请求
      const data = await http.post('/auth/login', formData);

      // 保存 token
      localStorage.setItem('token', data.token);
      localStorage.setItem('userInfo', JSON.stringify(data));

      // 跳转到首页
      navigate('/dashboard');
    } catch (err) {
      setError(err.message);
    } finally {
      setLoading(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        placeholder="用户名"
        value={formData.username}
        onChange={(e) => setFormData({ ...formData, username: e.target.value })}
      />
      <input
        type="password"
        placeholder="密码"
        value={formData.password}
        onChange={(e) => setFormData({ ...formData, password: e.target.value })}
      />
      {error && <div className="error">{error}</div>}
      <button type="submit" disabled={loading}>
        {loading ? '登录中...' : '登录'}
      </button>
    </form>
  );
}

6.2 处理异步状态

// hooks/useRequest.js
import { useState, useCallback } from 'react';

export function useRequest(apiFunc, options = {}) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const execute = useCallback(async (...args) => {
    setLoading(true);
    setError(null);

    try {
      const result = await apiFunc(...args);
      setData(result);
      options.onSuccess?.(result);
      return result;
    } catch (err) {
      setError(err);
      options.onError?.(err);
      throw err;
    } finally {
      setLoading(false);
    }
  }, [apiFunc, options]);

  return { data, loading, error, execute };
}

// 使用
function UserProfile({ userId }) {
  const { data: user, loading, error, execute: fetchUser } = useRequest(
    userApi.getUserInfo
  );

  useEffect(() => {
    fetchUser(userId);
  }, [userId]);

  if (loading) return <Spinner />;
  if (error) return <ErrorMessage error={error} />;
  return <div>{user?.name}</div>;
}

6.3 请求重试机制

// utils/retry.js
export async function requestWithRetry(
  requestFn,
  maxRetries = 3,
  delay = 1000
) {
  let lastError;

  for (let i = 0; i < maxRetries; i++) {
    try {
      return await requestFn();
    } catch (error) {
      lastError = error;

      // 不重试 4xx 错误(客户端错误)
      if (error.response?.status >= 400 && error.response?.status < 500) {
        throw error;
      }

      // 最后一次重试不再等待
      if (i < maxRetries - 1) {
        // 指数退避:1s, 2s, 4s...
        const waitTime = delay * Math.pow(2, i);
        console.log(`第 ${i + 1} 次失败,${waitTime}ms 后重试...`);
        await new Promise(resolve => setTimeout(resolve, waitTime));
      }
    }
  }

  throw lastError;
}

// 使用
const user = await requestWithRetry(() => fetchUser(userId));

6.4 并发请求控制

// 1. 并行请求(Promise.all)
const [users, orders, products] = await Promise.all([
  userApi.getUserList(),
  orderApi.getOrderList(),
  productApi.getProductList()
]);

// 2. 竞速请求(Promise.race)
const result = await Promise.race([
  fetchUser(userId),
  new Promise((_, reject) => 
    setTimeout(() => reject(new Error('请求超时')), 5000)
  )
]);

// 3. 限流请求(控制并发数)
async function limitedRequest(urls, limit = 3) {
  const results = [];
  const executing = [];

  for (const url of urls) {
    const promise = fetch(url).then(res => res.json());
    results.push(promise);

    if (urls.length >= limit) {
      const e = promise.then(() => executing.splice(executing.indexOf(e), 1));
      executing.push(e);
      if (executing.length >= limit) {
        await Promise.race(executing);
      }
    }
  }

  return Promise.all(results);
}

来源:
https://xbivx.cn/

相关文章
|
1月前
|
XML 前端开发 程序员
初级程序员必备的十大技能之 API 接口与前后端联调(一)
教程来源 http://qeext.cn/ 本文系统讲解API设计规范(RESTful/GraphQL)、HTTP协议核心(方法、状态码、头信息)、前后端联调流程及调试工具,助你打造标准化、高可用接口,打破前后端协作孤岛。
|
1月前
|
前端开发 程序员 API
初级程序员必备的十大技能之 API 接口与前后端联调(五)
教程来源 https://xgmoi.cn/ 本文系统梳理API联调核心知识:涵盖CORS跨域、404/401/403错误排查、数据格式转换、重复请求防控等高频问题及代码级解决方案;详解接口文档规范与Swagger自动化实践,并总结HTTP协议、RESTful设计、前端封装、调试工具等完整知识体系。
|
1月前
|
人工智能 监控 测试技术
AI 测试用例审核 Skill:把用例评审从“凭经验”变成“可评分”
本文介绍一种AI驱动的测试用例审核Skill,将资深测试负责人的评审经验封装为可复用、可量化、可批量执行的标准能力。它能自动检查逻辑完整性、预期明确性、前置条件、PRD覆盖度及边界异常,逐条评分、定位问题、给出修改建议,助力团队提升用例质量、统一评审标准、加速新人成长。
|
1月前
|
存储 人工智能 自然语言处理
2026年阿里云新老用户最新优惠活动:云服务器活动、免费试用活动、AI产品活动参考
阿里云2026新老用户优惠活动涵盖三大板块。云服务器方面,轻量应用服务器低至38元/年,经济型e实例99元/年,u1实例199元/年,限时限量抢购。免费试用方面,新老用户可领最高200元试用点,AI产品免费提供7000万+大模型tokens及30+款产品体验,140+云产品最长12个月免费试用。AI产品方面,百炼Token Plan支持多模型切换、多档套餐;HappyHorse视频生成模型限时8折;OpenClaw一键部署低至9.9元起。此外还提供折扣券、学生无门槛券、算力补贴等多类优惠券,整体以"普惠基础设施+零成本体验+智能化赋能"策略,全面降低上云与用AI门槛。
2026年阿里云新老用户最新优惠活动:云服务器活动、免费试用活动、AI产品活动参考
|
1月前
|
搜索推荐 程序员
初级程序员必备的十大技能之问题排查与自学能力(一)
教程来源 http://qeext.cn/ 本文系统讲解程序员两大终极能力:问题排查与自学方法。涵盖六步调试法、二分/排除/对比定位技巧、错误解读、高效搜索、文档阅读及结构化学习路径,助你从“能写代码”进阶为“稳解难题、快学新技术”的高价值工程师。
|
1月前
|
存储 弹性计算 人工智能
2026年阿里云优惠券领取及使用教程,新购、续费、升级可用!
阿里云2026年推出多类优惠券(代金券、满减券、折扣券),覆盖学生300元无门槛券、新用户10元满减、AI焕新季礼包等,适用于ECS、OSS等主流云产品,不支持域名及云市场商品。可通过权益中心、高校计划等入口领取,登录费用中心查看并结算时自动抵扣。
217 6
|
1月前
|
机器学习/深度学习 数据采集 算法
PCB电路板缺陷检测数据集分享(适用于YOLO系列深度学习检测任务)
本数据集专为PCB缺陷检测设计,含1500张1024×1024图像(训练集1000张、验证集500张),标注6类常见缺陷(缺失孔、鼠咬痕、开路等),采用YOLO格式,开箱即用,适配YOLOv5/v8等主流模型,助力工业质检与AI研发。(239字)
312 6
|
1月前
|
人工智能 弹性计算 API
阿里云轻量应用服务器低成本部署OpenClaw方案:2核2G38元,2核4G199元,全球多地域可选
2026年阿里云轻量应用服务器低成本部署OpenClaw AI助理的方案:用户可通过每天10:00和15:00的限量抢购活动,以38元/年(2核2G/40G云盘)或9.9元/月、199元/年(2核4G/50G云盘)的价格入手服务器,预装OpenClaw镜像实现分钟级一键部署,免代码上手。部署后可通过Web UI或飞书、钉钉、QQ、企业微信等IM工具与AI智能体交互,并支持扩展Skill和自定义RPA流程。方案覆盖个人博客、AI应用开发等场景,大幅降低了AI Agent的技术与资金门槛,是低成本拥抱AI智能体的实用路径。
|
1月前
|
运维 监控 Linux
初级程序员必备的十大技能之基础 Linux 命令(五)
教程来源 http://xgmoi.cn/ 本节汇总Linux系统监控与管理核心命令:磁盘(df/du)、内存(free)、运行状态(uptime/ uname)、打包压缩(tar/zip)、用户权限、日志查看及速查表,覆盖运维日常高频操作,简洁实用。
|
1月前
|
程序员 Shell 持续交付
初级程序员必备的十大技能之开发工具熟练使用(二)
教程来源 https://zlpow.cn/ 命令行是程序员高效开发的“第二语言”:涵盖文件操作、进程管理、网络诊断、管道重定向、Shell脚本及终端增强工具,助你快速定位问题、批量处理任务、自动化部署,全面提升系统操控力与生产力。