技术问题解决分享

记录开发中遇到的问题及解决方案

前端开发问题

问题: React组件状态更新但视图不刷新

React 状态管理 中等

2023-10-15

在使用React Hooks时,状态通过useState更新,但组件视图没有相应刷新。

现象: 控制台日志显示状态已改变,但DOM没有更新。

解决方案

这个问题通常是由于状态的不正确更新导致的,特别是当状态是对象或数组时。

根本原因: React使用浅比较来判断是否需要重新渲染,直接修改对象或数组的属性不会触发更新。

正确做法:

// 错误方式 - 不会触发更新
const [user, setUser] = useState({name: 'John', age: 30});
user.age = 31;  // 直接修改
setUser(user);  // 引用未变,React不会重新渲染

// 正确方式 - 创建新对象
setUser({...user, age: 31});

其他可能原因:

问题: API跨域请求被浏览器阻止

CORS 前端 后端 简单

2023-10-18

前端应用尝试访问不同域的API时,浏览器控制台显示CORS错误。

解决方案

跨域资源共享(CORS)是浏览器的安全机制,需要在服务器端配置。

后端解决方案(Node.js示例):

// Express中间件配置
app.use((req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
    next();
});

前端临时解决方案(仅开发环境):

问题: Vue 3 Composition API中watch无效

Vue Composition API 中等

2023-10-20

在Vue 3中使用Composition API时,watch函数没有按预期触发。

现象: 监听的响应式变量已改变,但watch回调没有执行。

解决方案

这通常是由于watch的依赖项不是响应式数据或watch配置不正确导致的。

常见原因及解决方案:

  1. 确保监听的源是响应式的:

    // 错误示例
    let count = 0;
    watch(count, (newVal) => { ... }); // 不会工作,count不是响应式的
    
    // 正确示例
    import { ref, watch } from 'vue';
    const count = ref(0);
    watch(count, (newVal) => { ... }); // 正常工作
  2. 深度监听对象:

    const state = reactive({ user: { name: 'John' } });
    
    // 默认浅监听,user对象内部变化不会触发
    watch(() => state.user, (newVal) => { ... });
    
    // 添加deep选项进行深度监听
    watch(() => state.user, (newVal) => { ... }, { deep: true });

后端开发问题

问题: Node.js中MySQL连接池连接泄漏

Node.js MySQL 数据库 困难

2023-10-22

使用mysql2库的连接池时,随着时间推移,应用会耗尽所有连接并停止响应。

现象: 数据库连接数逐渐增加直到达到上限,应用无法处理新请求。

解决方案

连接泄漏通常是由于未正确释放数据库连接导致的。

正确使用连接池的模式:

const mysql = require('mysql2/promise');

// 创建连接池
const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    database: 'test',
    waitForConnections: true,
    connectionLimit: 10,
    queueLimit: 0
});

// 正确使用方式 - 使用try/catch/finally确保连接释放
async function queryUser(id) {
    let connection;
    try {
        connection = await pool.getConnection();
        const [rows] = await connection.query('SELECT * FROM users WHERE id = ?', [id]);
        return rows[0];
    } catch (err) {
        console.error('Query failed:', err);
        throw err;
    } finally {
        if (connection) connection.release(); // 确保连接释放
    }
}

调试连接泄漏的技巧:

问题: Python Flask应用内存持续增长

Python Flask 内存泄漏 困难

2023-10-25

Flask应用在长时间运行后内存使用量持续增加,最终导致性能下降或被系统终止。

解决方案

内存泄漏可能由多种原因引起,以下是常见原因及解决方案:

1. 全局变量积累数据

# 错误示例 - 全局列表不断增长
cache = []

@app.route('/add')
def add_item():
    cache.append(request.args.get('item'))  # 内存泄漏!
    return "Item added"

解决方案: 使用适当的数据结构并定期清理,或使用Redis等外部缓存

2. 未关闭数据库连接或文件句柄

# 错误示例 - 未关闭数据库连接
@app.route('/users')
def get_users():
    conn = get_db_connection()  # 每次请求都创建新连接
    users = conn.query('SELECT * FROM users')
    return jsonify(users)       # 忘记conn.close()!

解决方案: 使用上下文管理器或try/finally块确保资源释放

调试工具:

DevOps问题

问题: Docker容器内应用时区不正确

Docker 时区 DevOps 简单

2023-10-28

Docker容器内的应用显示的时间与宿主机不一致,通常是UTC时间而非本地时间。

解决方案

默认情况下,Docker容器使用UTC时区。以下是几种设置正确时区的方法:

方法1: 通过环境变量设置

# docker-compose.yml示例
services:
  myapp:
    image: myapp
    environment:
      - TZ=Asia/Shanghai

方法2: 挂载宿主机的时区文件

# docker run 命令示例
docker run -v /etc/timezone:/etc/timezone:ro -v /etc/localtime:/etc/localtime:ro myapp

方法3: 在Dockerfile中设置

# Dockerfile示例
FROM alpine
RUN apk add --no-cache tzdata
ENV TZ Asia/Shanghai

验证时区:

# 进入容器执行
date
cat /etc/timezone

问题: Nginx返回413 Request Entity Too Large错误

Nginx 文件上传 简单

2023-11-01

当用户尝试上传较大文件时,Nginx返回413错误,阻止了文件上传。

解决方案

这是由于Nginx默认限制客户端请求体大小导致的,默认值为1MB。

解决方案1: 调整client_max_body_size

# 在nginx.conf或站点配置的http/server/location块中添加
client_max_body_size 20M;  # 设置为20MB,根据需要调整

解决方案2: 针对特定路由设置

server {
    # 其他配置...

    location /upload {
        client_max_body_size 50M;  # 仅对/upload路由设置50MB限制
        # 其他上传相关配置...
    }
}

注意事项: