You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js中如何从promisify后的sqlite3 run方法获取插入ID或受影响行数?

解决sqlite3 promisify后run方法无法获取lastID/changes的问题

可以做到,无需额外封装包。核心问题是util.promisify默认只处理回调的参数,而sqlite3的run方法把lastID和changes挂在回调的this上下文中,而非回调参数里。下面提供两种原生实现方案:

方案一:手动封装Promise版本的run方法

直接写一个函数,将db.run的回调逻辑包装成Promise,在回调中提取this上的lastID和changes:

const sqlite3 = require('sqlite3').verbose();
const db = new sqlite3.Database(':memory:');

function runAsync(db, sql, params = []) {
  return new Promise((resolve, reject) => {
    db.run(sql, params, function(err) {
      if (err) {
        reject(err);
      } else {
        // 从回调的this中提取所需数据
        resolve({ lastID: this.lastID, changes: this.changes });
      }
    });
  });
}

// 使用示例
async function demo() {
  // 创建表
  await runAsync(db, 'CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)');
  // 插入数据并获取结果
  const insertResult = await runAsync(db, 'INSERT INTO users (name) VALUES (?)', ['Alice']);
  console.log('插入ID:', insertResult.lastID); // 输出 1
  console.log('受影响行数:', insertResult.changes); // 输出 1

  // 更新数据
  const updateResult = await runAsync(db, 'UPDATE users SET name = ? WHERE id = ?', ['Alicia', 1]);
  console.log('更新受影响行数:', updateResult.changes); // 输出 1
}

demo().catch(err => console.error(err));

方案二:自定义util.promisify的行为

利用util.promisify.custom属性,给db.run定制Promise化的逻辑,这样后续可以直接用util.promisify生成异步方法:

const sqlite3 = require('sqlite3').verbose();
const util = require('util');
const db = new sqlite3.Database(':memory:');

// 给db.run添加自定义promisify逻辑
db.run[util.promisify.custom] = function(sql, params) {
  return new Promise((resolve, reject) => {
    this.run(sql, params, function(err) {
      if (err) {
        reject(err);
      } else {
        resolve({ lastID: this.lastID, changes: this.changes });
      }
    });
  });
};

// 生成promisify后的run方法
const runAsync = util.promisify(db.run);

// 使用示例
async function demo() {
  await runAsync('CREATE TABLE products (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)');
  const result = await runAsync('INSERT INTO products (name) VALUES (?)', ['Laptop']);
  console.log('插入ID:', result.lastID); // 输出 1
}

demo().catch(err => console.error(err));

两种方案都完全基于原生sqlite3和util包,不需要引入额外依赖,核心都是在Promise的resolve阶段,从run方法回调的this上下文里提取lastID和changes并返回。

内容的提问来源于stack exchange,提问作者HimmDawg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:35:20