React Native SQLite应用与PostgreSQL后端数据库双向同步实现方案咨询
React Native SQLite应用与PostgreSQL后端数据库双向同步实现方案咨询
看起来你已经搞定了前端到后端的单向同步,现在就差后端变动同步回前端这一步了对吧?我来给你梳理几个实用的方案,都是实际项目里验证过的思路:
1. 定时轮询(入门首选,实现成本最低)
这是最容易上手的方案,不需要对后端做太大改造:
- 前端每隔固定时间(比如30秒、1分钟,根据你的实时性需求调整)调用后端接口,拉取完整的todo列表或者增量更新(比如只拉取上次同步之后修改的todo)
- 拿到后端数据后,和本地SQLite里的数据做对比,把新增、修改、删除的条目同步到本地,然后更新UI
- 优化点:给每个todo加
last_updated_at字段,后端接口支持按时间范围查询(比如GET /todos?after=2024-05-20T12:00:00),这样每次只拉取变化的数据,减少请求量
简单代码示例(React Native里用Hooks):
import { useEffect, useState } from 'react'; import { getTodosFromBackend, updateLocalTodos, getLocalTodos, getLastSyncTimeFromLocal, saveLastSyncTimeToLocal } from './your-utils'; function TodoList() { const [todos, setTodos] = useState([]); // 定时同步逻辑 useEffect(() => { const syncInterval = setInterval(async () => { // 从本地获取上次同步的时间戳 const lastSyncTime = await getLastSyncTimeFromLocal(); // 拉取后端自上次同步后的变更数据 const updatedTodos = await getTodosFromBackend(lastSyncTime); if (updatedTodos.length > 0) { // 更新本地SQLite数据 await updateLocalTodos(updatedTodos); // 刷新UI状态 const latestLocalTodos = await getLocalTodos(); setTodos(latestLocalTodos); // 保存本次同步时间 await saveLastSyncTimeToLocal(new Date().toISOString()); } }, 30000); // 30秒同步一次 return () => clearInterval(syncInterval); // 组件卸载时清除定时器 }, []); // 其他渲染逻辑... }
优点:实现简单,不需要后端支持实时推送;缺点:有延迟,频繁请求会消耗网络和电池资源,适合对实时性要求不高的场景。
2. WebSocket实时推送(实时性最高)
如果你的需求是后端一改,前端立刻更新,那WebSocket是最佳选择:
- 后端搭建WebSocket服务(比如用Node.js的
ws库,或者Socket.io更易用,支持自动重连) - 给PostgreSQL的
todos表加触发器,当有INSERT/UPDATE/DELETE操作时,把变更的数据推送给WebSocket服务;或者在后端的业务接口里,每次处理完数据库变更后,主动通过WebSocket推送消息给所有连接的客户端 - 前端React Native里用
socket.io-client连接后端的WebSocket服务,监听todos-changed之类的事件,收到消息后立刻更新本地SQLite和UI
代码示例:
前端(React Native)
import io from 'socket.io-client'; import { updateLocalTodos, getLocalTodos } from './your-db-utils'; // 连接后端WebSocket服务 const socket = io('http://your-backend-domain:3000', { reconnection: true, // 自动重连 reconnectionDelay: 1000 // 重连间隔 }); function TodoList() { const [todos, setTodos] = useState([]); useEffect(() => { // 监听todo变更事件 socket.on('todo-updated', async (changedTodos) => { // 同步变更到本地SQLite await updateLocalTodos(changedTodos); // 刷新UI const latestTodos = await getLocalTodos(); setTodos(latestTodos); }); // 监听连接状态 socket.on('connect', () => console.log('WebSocket连接成功')); socket.on('disconnect', () => console.log('WebSocket断开,正在重连...')); return () => socket.disconnect(); // 组件卸载时断开连接 }, []); // 其他逻辑... }
后端(Node.js + Express + Socket.io)
const express = require('express'); const { Server } = require('socket.io'); const http = require('http'); const { Pool } = require('pg'); const app = express(); const server = http.createServer(app); // 初始化Socket.io,允许前端跨域连接 const io = new Server(server, { cors: { origin: '*' } }); // PostgreSQL连接池 const pool = new Pool({ user: 'your-db-user', host: 'your-db-host', database: 'your-db-name', password: 'your-db-password', port: 5432 }); // 示例:更新todo的后端接口 app.put('/todos/:id', express.json(), async (req, res) => { const { id } = req.params; const { title, completed } = req.body; const result = await pool.query( 'UPDATE todos SET title = $1, completed = $2, last_updated_at = NOW() WHERE id = $3 RETURNING *', [title, completed, id] ); if (result.rows.length > 0) { // 推送更新给所有在线客户端 io.emit('todo-updated', [result.rows[0]]); res.json(result.rows[0]); } else { res.status(404).json({ error: 'Todo不存在' }); } }); // 监听WebSocket连接 io.on('connection', (socket) => { console.log(`客户端 ${socket.id} 连接成功`); socket.on('disconnect', () => console.log(`客户端 ${socket.id} 断开连接`)); }); server.listen(3000, () => console.log('后端服务运行在3000端口'));
优点:实时性强,后端变更立刻推送到前端;缺点:需要搭建和维护WebSocket服务,处理重连、断线重连等边缘情况,适合对实时性要求高的场景。
3. 基于PostgreSQL原生能力的实时订阅
PostgreSQL本身支持LISTEN/NOTIFY功能,你可以直接利用这个特性来实现后端数据变更的通知:
- 给
todos表加触发器,当数据变更时,用NOTIFY发送消息到指定的频道 - 后端服务监听这个PostgreSQL频道,收到消息后再推送给前端(用WebSocket或者HTTP长轮询)
- 前端收到通知后更新本地数据
这个方案的优点是不需要在业务代码里手动触发推送,完全由数据库触发器处理,适合后端有多个服务修改数据库的场景。
关键注意事项:冲突处理
双向同步绕不开的问题是数据冲突(比如前端和后端同时修改了同一个todo),这里给你两个常用的解决思路:
- 版本号机制:给每个todo加
version字段,每次更新时,后端检查版本号是否和客户端提交的一致,不一致则拒绝更新(乐观锁);同步时,版本号高的覆盖版本号低的 - 最后修改时间:给每个todo加
last_updated_at字段,同步时以最新的修改时间为准,自动覆盖旧数据(适合冲突概率低的场景)
现成工具推荐(减少重复造轮子)
如果不想自己写同步逻辑,可以试试这些工具:
- Supabase:基于PostgreSQL的BaaS平台,自带实时订阅功能,React Native里用官方的
@supabase/supabase-js库,几行代码就能监听数据库表的变更,然后同步到本地SQLite - WatermelonDB:专为React Native设计的前端数据库,支持自定义同步逻辑,你可以结合它的同步适配器来对接PostgreSQL后端,它内置了增量同步和冲突处理的能力
内容来源于stack exchange
相关产品推荐
相关产品推荐

