如何检测CSV数据全部插入PostgreSQL完成(Node.js场景)
问题分析与修复方案
你的代码存在几个核心问题,导致无法正确等待所有插入完成并返回预期结果:
- 回调与async/await混用导致await失效:
pool.connect()的回调版本并非Promise,await它不会等待回调内的逻辑执行完毕,testres函数会直接结束,自然返回undefined。 - forEach无法等待异步操作:
csvData.forEach(async row => {})中的异步函数不会被forEach等待,循环会直接走完并执行done()释放连接,此时插入操作可能还未完成。 - 回调内的return不影响外层函数:你在
client.query的回调里return 'finished !!!!!',这个return仅属于回调函数,和testres的返回值无关。 - countrec未初始化且依赖全局变量:这种统计方式容易出现竞态问题,导致计数不准确。
修复后的代码
import * as pg from 'pg'; const { Pool } = pg.default; import { parse } from "fast-csv"; import { testres1 } from './createpdf.js'; const testres = async () => { const pool = new Pool({ connectionString: conString, idleTimeoutMillis: 0, connectionTimeoutMillis: 0, ssl: { rejectUnauthorized: false, }, }); const query = "INSERT INTO _staging(firstName, lastName, Employee_ID, Employee_Unique_ID) \ VALUES($1, $2, $3, $4) RETURNING Employee_ID"; // 使用Promise版本的connect获取客户端 const client = await pool.connect(); try { // 移除CSV表头行 csvData.shift(); // 生成所有插入操作的Promise数组 const insertPromises = csvData.map(row => { return client.query(query, row) .catch(err => { console.error(err.stack + "error row:", row); throw err; // 抛出错误让Promise.all统一处理 }); }); // 等待所有插入操作完成 await Promise.all(insertPromises); // 所有插入完成后返回成功信息 return 'finished !!!!!'; } finally { // 确保无论成功失败都释放连接 client.release(); } }; // 顶层执行逻辑(避免直接在模块顶层使用await的兼容性问题) (async () => { try { const ddd = await testres(); console.log('test :', ddd); // 此处会输出'finished !!!!!' const eee = await testres1(); } catch (err) { console.error('操作失败:', err); } })();
关键修复说明
- 改用Promise版API:使用
await pool.connect()获取客户端,这是pg库的原生Promise接口,能正确等待连接建立。 - 用Promise.all批量等待异步操作:通过
map生成所有插入操作的Promise数组,再用Promise.all()等待全部完成,确保所有记录插入后才继续执行后续逻辑。 - 统一错误处理:在每个插入Promise中捕获错误并抛出,让
Promise.all()能及时感知失败,最终在顶层try/catch中统一处理。 - 安全释放连接:将连接释放放在
finally块中,避免因错误导致连接泄漏。
内容的提问来源于stack exchange,提问作者Roger Holland
相关产品推荐
相关产品推荐

