4、数据源对接:API接口设计、WebSocket实时数据、静态数据模拟
数据源对接,说白了就是大屏的「粮食供应」问题。
你想想看,大屏做得再炫酷,如果数据拿不到、拿不准、拿不快,那跟一张静态海报有什么区别?我个人习惯把数据源分成三类来对待:API接口、WebSocket实时流、静态模拟数据。这三者各有各的用场,也各有各的坑。
4.1 API接口设计:别让后端猜你要什么
我在项目中遇到过最头疼的事,就是前端和后端对接口字段的理解不一致。后端返回一个 status,前端以为是 0/1,后端给的是 true/false。这种问题在开发阶段还好,上了生产环境就是事故。
所以,我建议在项目启动时,先和后端敲定一份接口规范。别嫌麻烦,这是省时间的捷径。
核心原则:接口设计要「前端友好」。后端不要返回嵌套过深的数据结构,尽量扁平化。
举个例子,一个典型的大屏数据接口,我通常会这样设计:
// 请求示例
GET /api/dashboard/overview
// 响应示例
{
"code": 200,
"message": "success",
"data": {
"totalUsers": 12890,
"activeUsers": 3456,
"todayOrders": 892,
"revenue": 456789.00,
"trendData": [
{ "date": "2024-01-01", "value": 1200 },
{ "date": "2024-01-02", "value": 1350 }
],
"alerts": [
{ "id": 1, "level": "warning", "message": "服务器负载过高" }
]
}
}
嗯,这里要注意几个细节:
- 统一返回格式:code、message、data 三层结构,前端统一处理错误
- 时间格式:统一用 ISO 8601 格式,别搞什么时间戳和字符串混用
- 空值处理:数组为空返回
[],不要返回null - 分页参数:统一用
page和pageSize,别用offset和limit
我的小技巧:在项目初期,我会用 Postman 或 Swagger 先模拟一套接口文档。前端先按这个文档开发,后端再按这个文档实现。这样两边可以并行推进,互不阻塞。
4.2 WebSocket实时数据:别让大屏变成「死屏」
大屏最怕什么?最怕数据不动。
你想想看,一个监控大屏,如果数据每隔 30 秒才刷新一次,那跟看 PPT 有什么区别?实时数据,必须用 WebSocket。
我曾经在一个智慧城市项目中,一开始用了轮询(Polling),每 5 秒请求一次接口。结果呢?服务器压力大,前端页面卡顿,用户体验极差。后来改成 WebSocket,问题迎刃而解。
避坑指南:我曾经在 WebSocket 连接上吃过亏——没有做断线重连。结果网络波动一下,大屏就「死」了,数据一动不动,直到运维手动刷新页面。后来我学乖了,一定要加上重连机制。
一个健壮的 WebSocket 连接,我通常会这样封装:
class RealtimeSocket {
constructor(url) {
this.url = url;
this.ws = null;
this.reconnectInterval = 3000; // 3秒重连
this.init();
}
init() {
this.ws = new WebSocket(this.url);
this.ws.onopen = () => {
console.log('WebSocket 连接成功');
// 可以发送订阅消息
this.ws.send(JSON.stringify({ type: 'subscribe', channel: 'dashboard' }));
};
this.ws.onmessage = (event) => {
const data = JSON.parse(event.data);
// 触发自定义事件,让组件订阅
window.dispatchEvent(new CustomEvent('realtime-data', { detail: data }));
};
this.ws.onclose = () => {
console.log('WebSocket 断开,准备重连...');
setTimeout(() => this.init(), this.reconnectInterval);
};
this.ws.onerror = (err) => {
console.error('WebSocket 错误:', err);
this.ws.close();
};
}
send(data) {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
}
// 使用示例
const socket = new RealtimeSocket('wss://api.example.com/ws');
这里有几个关键点:
- 心跳检测:每隔 30 秒发一个 ping,确保连接存活
- 消息格式:统一用 JSON,包含 type 和 payload 字段
- 订阅机制:不要一股脑把所有数据都推过来,按频道订阅
- 数据缓存:断线重连后,先拉一次全量数据,再接收增量更新
性能建议:WebSocket 消息不要过于频繁。我见过有人每秒推送 100 次数据,结果浏览器渲染跟不上,页面直接卡死。一般来说,每秒 10-20 次更新就足够了。如果数据变化太快,可以在后端做降频处理。
4.3 静态数据模拟:开发阶段的「救命稻草」
说实话,大屏开发最怕等后端接口。
后端说「接口明天好」,结果拖了一周。前端干等着?不行。所以,我习惯在项目一开始就准备一套静态模拟数据。
静态数据模拟,说白了就是「造假数据」。但造假也要造得专业。
我通常会建一个 mock 文件夹,里面放各种数据文件:
// mock/dashboard.js
export const mockOverview = {
totalUsers: 12890,
activeUsers: 3456,
todayOrders: 892,
revenue: 456789.00,
trendData: Array.from({ length: 30 }, (_, i) => ({
date: `2024-01-${String(i + 1).padStart(2, '0')}`,
value: Math.floor(Math.random() * 2000) + 500
}))
};
// 模拟实时数据
export const mockRealtimeData = () => ({
timestamp: Date.now(),
cpuUsage: (Math.random() * 100).toFixed(2),
memoryUsage: (Math.random() * 100).toFixed(2),
networkTraffic: Math.floor(Math.random() * 10000)
});
我的经验:模拟数据要尽量「真实」。比如用户量不能忽高忽低,要有趋势变化。我通常会写一个简单的数据生成器,模拟出「早上低、下午高、晚上回落」的规律。这样开发出来的大屏,视觉效果才自然。
静态数据模拟的好处很明显:
- 前端独立开发:不用等后端,自己就能跑起来
- 边界测试:可以模拟各种极端情况,比如数据为空、数据量超大、数据格式错误
- 演示方便:给客户演示时,不用依赖真实环境,本地就能跑
注意:模拟数据不能「太完美」。我曾经犯过一个错误——模拟数据全是整数、全是正数、全是规律变化。结果上线后,真实数据一进来,图表显示异常。所以,模拟数据里一定要包含一些「脏数据」:比如 null、负数、超大值、空字符串。这样才能提前发现前端代码的健壮性问题。
4.4 三种数据源的切换策略
在实际项目中,这三种数据源不是互斥的,而是可以灵活切换的。
我通常会在项目中设计一个数据源切换层:
// dataSource.js
const DATA_SOURCE = {
MOCK: 'mock',
API: 'api',
WEBSOCKET: 'websocket'
};
// 当前数据源,可以通过环境变量或配置切换
const currentSource = process.env.VUE_APP_DATA_SOURCE || DATA_SOURCE.MOCK;
export async function fetchOverview() {
switch (currentSource) {
case DATA_SOURCE.MOCK:
return mockOverview;
case DATA_SOURCE.API:
return axios.get('/api/dashboard/overview').then(res => res.data);
case DATA_SOURCE.WEBSOCKET:
// 通过 WebSocket 获取,这里返回一个 Promise
return new Promise((resolve) => {
const handler = (event) => {
resolve(event.detail);
window.removeEventListener('realtime-data', handler);
};
window.addEventListener('realtime-data', handler);
});
}
}
这样做的好处是:
- 开发阶段:用 mock 数据,快速迭代
- 联调阶段:切换到 API,对接真实接口
- 生产环境:切换到 WebSocket,接收实时数据
而且,切换只需要改一个配置变量,不用改任何业务代码。
总结一下:数据源对接这件事,看似简单,但做不好就是大坑。API 接口要规范,WebSocket 要健壮,静态数据要真实。三者灵活切换,才能让大屏开发事半功倍。
嗯,下一章我们会聊到「数据可视化组件选型与封装」,到时候再细说怎么把这些数据漂亮地展示出来。