Express Mock API

发布于:2025-06-22 ⋅ 阅读:(20) ⋅ 点赞:(0)

这段代码是一个基于 Express 框架的模拟 API 实现,用于前端开发中模拟后端接口的响应。下面我将从多个角度详细解析这段代码:

import type { Request, Response } from 'express';

export default {
  'POST  /api/register': (_: Request, res: Response) => {
    res.send({
      data: { status: 'ok', currentAuthority: 'user' },
    });
  },
};

核心功能解析

1. 导入 Express 类型

import type { Request, Response } from 'express';
  • import type: TypeScript 特性,只导入类型声明,不导入实际实现

  • Request: Express 请求对象类型(包含请求参数、头信息等)

  • Response: Express 响应对象类型(用于发送响应)

2. 导出模拟 API 对象

export default {
  // API 定义
};
  • 导出一个包含路由配置的对象

  • 键名格式:<HTTP方法> <路由路径>

  • 键值:处理该路由的函数

3. 注册接口实现

'POST  /api/register': (_: Request, res: Response) => {
  res.send({
    data: { status: 'ok', currentAuthority: 'user' },
  });
}
  • 路由定义POST /api/register

  • 参数

    • _: Request:忽略请求对象(使用 _ 表示未使用)

    • res: Response:响应对象

  • 响应内容

{
  "data": {
    "status": "ok",
    "currentAuthority": "user"
  }
}

在项目中的使用场景

1. 前端开发阶段

  • 当后端 API 尚未完成时

  • 需要独立测试前端功能时

2. 单元测试

  • 模拟 API 响应进行组件测试

3. 演示与原型开发

  • 快速搭建演示系统

实际应用示例(在 Ant Design Pro 中)

配置 mock 服务

// mock/user.ts
import type { Request, Response } from 'express';

export default {
  // 注册接口
  'POST /api/register': (req: Request, res: Response) => {
    const { username, password } = req.body;
    
    // 模拟不同响应
    if (username === 'admin') {
      return res.status(400).send({
        error: '用户名已存在'
      });
    }
    
    res.send({
      data: { 
        status: 'ok', 
        currentAuthority: username === 'super' ? 'admin' : 'user' 
      }
    });
  },
  
  // 登录接口
  'POST /api/login': (req: Request, res: Response) => {
    const { username, password } = req.body;
    
    if (username === 'admin' && password === 'ant.design') {
      return res.send({
        status: 'ok',
        currentAuthority: 'admin',
        token: 'mock-token-admin-123'
      });
    }
    
    if (username === 'user' && password === 'ant.design') {
      return res.send({
        status: 'ok',
        currentAuthority: 'user',
        token: 'mock-token-user-123'
      });
    }
    
    res.status(401).send({
      error: '用户名或密码错误'
    });
  },
  
  // 获取当前用户信息
  'GET /api/currentUser': (_: Request, res: Response) => {
    res.send({
      name: 'Serati Ma',
      avatar: 'https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png',
      userid: '00000001',
      email: 'antdesign@alipay.com',
      signature: '海纳百川,有容乃大',
      title: '交互专家',
      group: '蚂蚁金服-某某某事业群-某某平台部-某某技术部-UED',
      tags: [
        { key: '0', label: '很有想法的' },
        { key: '1', label: '专注设计' },
      ],
      notifyCount: 12,
      unreadCount: 11,
      country: 'China',
      access: 'admin',
      geographic: {
        province: { label: '浙江省', key: '330000' },
        city: { label: '杭州市', key: '330100' },
      },
      address: '西湖区工专路 77 号',
      phone: '0752-268888888',
    });
  }
};

前端组件调用

// src/pages/user/Register/index.tsx
import { register } from '@/services/ant-design-pro/api';
import { useModel } from 'umi';

export default () => {
  const { initialState, setInitialState } = useModel('@@initialState');
  
  const handleSubmit = async (values: API.RegisterParams) => {
    try {
      const result = await register(values);
      if (result.status === 'ok') {
        // 更新全局状态
        setInitialState({
          ...initialState,
          currentUser: {
            ...initialState?.currentUser,
            authority: result.currentAuthority
          }
        });
        history.push('/');
      }
    } catch (error) {
      console.error('注册失败:', error);
    }
  };
  
  return (
    <ProForm onFinish={handleSubmit}>
      {/* 表单内容 */}
    </ProForm>
  );
};

高级 Mock 功能实现

1. 动态响应

// 根据请求参数返回不同响应
'POST /api/register': (req: Request, res: Response) => {
  const { username } = req.body;
  
  if (username === 'admin') {
    return res.status(400).send({
      error: '用户名已存在'
    });
  }
  
  res.send({
    data: { 
      status: 'ok', 
      currentAuthority: username === 'super' ? 'admin' : 'user' 
    }
  });
}

2. 延迟响应

// 模拟网络延迟
'POST /api/login': async (req: Request, res: Response) => {
  // 延迟1秒响应
  await new Promise(resolve => setTimeout(resolve, 1000));
  
  res.send({
    status: 'ok',
    token: 'mock-token-123'
  });
}

3. 状态码控制

// 返回不同HTTP状态码
'GET /api/protected': (req: Request, res: Response) => {
  const token = req.headers.authorization;
  
  if (!token || token !== 'Bearer mock-token-123') {
    return res.status(401).send({
      error: '未授权'
    });
  }
  
  res.send({
    data: '受保护的内容'
  });
}

4. 数据持久化(内存)

// 简易内存数据库
const mockDB = {
  users: [] as any[],
};

export default {
  'POST /api/users': (req: Request, res: Response) => {
    const newUser = { id: Date.now(), ...req.body };
    mockDB.users.push(newUser);
    res.send(newUser);
  },
  
  'GET /api/users': (req: Request, res: Response) => {
    res.send(mockDB.users);
  },
  
  'DELETE /api/users/:id': (req: Request, res: Response) => {
    const id = parseInt(req.params.id);
    mockDB.users = mockDB.users.filter(user => user.id !== id);
    res.send({ success: true });
  }
};

在 Ant Design Pro 中的集成方式

1. 配置文件

// config/config.ts
export default {
  // ...
  mock: {
    // 只包含需要的mock文件
    include: ['src/mock/user.ts', 'src/mock/product.ts']
  },
  // ...
};

2. 目录结构

src
├── mock
│   ├── user.ts        # 用户相关API
│   ├── product.ts     # 产品相关API
│   └── index.ts       # 统一导出
├── services
│   └── api.ts         # 前端API服务

3. 统一导出

// src/mock/index.ts
import user from './user';
import product from './product';

export default {
  ...user,
  ...product,
};

4. 启用/禁用 Mock

// .env
MOCK=none # 禁用所有mock
# 或
MOCK=user,product # 启用指定mock

Mock 数据的最佳实践

1. 数据生成工具

npm install mockjs --save-dev
import mockjs from 'mockjs';

export default {
  'GET /api/users': (req: Request, res: Response) => {
    const { current = 1, pageSize = 10 } = req.query;
    
    const data = mockjs.mock({
      'list|20': [{
        'id|+1': 1,
        'name': '@cname',
        'email': '@email',
        'phone': /^1[3456789]\d{9}$/,
        'address': '@county(true)',
        'avatar': "@image('200x200')"
      }]
    });
    
    res.send({
      success: true,
      data: data.list,
      total: 20,
      current,
      pageSize
    });
  }
};

2. 类型安全

// src/services/ant-design-pro/typings.d.ts
declare namespace API {
  type RegisterResult = {
    status?: 'ok' | 'error';
    currentAuthority?: 'user' | 'admin';
  };
  
  type RegisterParams = {
    username?: string;
    password?: string;
    confirmPassword?: string;
  };
}

// 在mock中使用
'POST /api/register': (_: Request, res: Response) => {
  const result: API.RegisterResult = {
    status: 'ok',
    currentAuthority: 'user'
  };
  
  res.send(result);
}

3. 环境区分

// 只在开发环境启用mock
if (process.env.NODE_ENV === 'development') {
  const { createProxyMiddleware } = require('http-proxy-middleware');
  
  module.exports = function(app: any) {
    app.use(
      '/api',
      createProxyMiddleware({
        target: 'http://localhost:3000',
        changeOrigin: true,
        pathRewrite: { '^/api': '' },
      })
    );
  };
}

4. 错误模拟

// 模拟网络错误
'POST /api/error': (req: Request, res: Response) => {
  // 50%概率返回错误
  if (Math.random() > 0.5) {
    return res.status(500).send({
      error: '服务器内部错误'
    });
  }
  
  res.send({ success: true });
}

Mock 服务的优缺点

优点:

  1. 前后端并行开发:不依赖后端完成接口

  2. 快速原型验证:立即看到数据展示效果

  3. 边界测试:轻松模拟各种异常情况

  4. 离线开发:无需网络连接即可开发

缺点:

  1. 数据真实性:可能与实际数据有差异

  2. 维护成本:需要同步更新真实API变更

  3. 逻辑缺失:无法模拟复杂的业务逻辑

  4. 性能差异:无法模拟真实API性能特征

总结

这段 Express Mock API 代码是前端开发中的重要工具:

  • 使用 import type 确保类型安全

  • 通过路由定义格式 <METHOD> <PATH> 声明接口

  • 忽略请求对象 (_) 表示不处理请求数据

  • 使用 res.send() 返回模拟数据

在 Ant Design Pro 等现代前端框架中:

  1. 将 Mock 文件放在 /mock 目录

  2. 使用标准格式定义路由和处理函数

  3. 结合 TypeScript 确保类型安全

  4. 通过环境变量控制 Mock 的启用状态

最佳实践包括:

  • 使用动态响应模拟不同场景

  • 添加延迟模拟网络环境

  • 实现简单的内存数据库

  • 使用 Mock.js 生成随机数据

  • 保持与真实 API 的同步更新

合理使用 Mock API 可以显著提高前端开发效率,但需注意在项目后期逐步替换为真实 API,确保系统功能的完整性和数据的一致性。


网站公告

今日签到

点亮在社区的每一天
去签到