【问题标题】:Error when doing anything else than SELECT with node-firebird in Electron app在 Electron 应用程序中使用 node-firebird 执行 SELECT 以外的任何操作时出错
【发布时间】:2019-03-29 17:40:17
【问题描述】:

我们必须重建一个应用程序,从各种数据库导入数据并将它们插入我们的数据库,在 Firebird 3 中(使用 node-firebird)。

在 NodeJS 项目中运行时,使用 Express 运行良好。

现在,我正在编写 POC 以将代码嵌入到 Electron 应用程序中。

每当我尝试执行 SELECT 以外的任何操作时,应用程序都会崩溃。

这是消息:

Error

at doCallback (index.js:1234)
at index.js:2929
at messages.js:126
at FSReqWrap.oncomplete (fs.js:141)

我没有任何其他消息。

我们使用的是 Electron 4.0.5、Node 10、Firebird 3.0.4(32 位) 节点火鸟

我们也尝试过:node-firebird-dev 但没有成功

这是一个简单的代码示例(使用“manukdadali”,node-firebird 上的异步包装器)。

const firebird = require('manukdadali');
const path = require('path');
const moment = require('moment');

class TestDB {
  constructor(folder) {
    this.options = {
      host: 'localhost',
      database: path.resolve(folder),
      user: 'SYSDBA',
      password: 'masterkey',
    };
  }

  insertData = async () => {
    const db = await firebird.connect(this.options);

    let rows = await db.query('select * from t_client');
    console.log(rows);
    try {
      rows = await db.query(
        `insert into t_client 
         (t_client_id, 
          matricule,
          nom,
          prenom,
          nom_jeune_fille,
          date_naissance,
          rang_gemellaire,
          langue,
          sexe,
          maison,
          etage,
          chambre,
          lit,
          commentaire_individuel,
          commentaire_global,
          t_profil_remise_id,
          t_personne_referente_id,
          facturation,
          date_derniere_visite
          ) values (
            4,
            '000233532',
            'NAME',
            'NAME2',
            'NAME3',
            '19700504',
            1,
            'FR',
            'M',
            '',
            '',
            '',
            '',
            '',
            '',
            1,
            1,
            '1',
            ''  
          )`);  
    } catch (error) {
      console.log(error); 
    }

  };
}

export { TestDB };

【问题讨论】:

  • 在 ISQL(或其他查询工具)中尝试插入时插入是否正确执行,例如,我发现您将空字符串插入名为 date_derniere_visite 的列中很可疑,这表明它是TIMESTAMPDATE 列,其中空字符串不是有效值。另外,插入不会产生行,分配给rows 在这里很奇怪,但我不确定这是否会导致错误。
  • 嗨,马克。谢谢你的回答。是的,我可以在 ISQL 中插入、更新、执行存储过程。问题只在 Electron 内部。一个简单的 Nodejs 脚本中的相同操作可以正常工作。
  • rows = await db.query - 但行集仅由 SELECT 查询类型生成。为什么你会期望任何其他查询产生行集???
  • 确实如此。但这不是重点。它应该返回“0”,但不会崩溃。
  • 当它不应该返回任何东西时为什么要“返回0”?

标签: node.js async-await electron firebird async.js


【解决方案1】:

因此,正如我所评论的,它与 Electron 中的流程相关联。 在 rederer 进程中,它崩溃了。

我将数据库访问和操作移至 MAIN 进程,它运行良好。 我现在在渲染器和主程序之间使用 IPC 通信。

谢谢大家:)

【讨论】:

    【解决方案2】:

    rowset 期望从插入语句中得到什么?有什么要返回的,更何况insert可以有什么多行结果?

     rows = await db.query(
        `insert into t_client ....
    

    看看Node-firebird 的描述 - 拉结果行是一种发布INSERT 的方法吗?

    这是那里的示例 - 它不使用行:

    // db = DATABASE
    db.query('INSERT INTO USERS (ID, ALIAS, CREATED) VALUES(?, ?, ?) RETURNING ID', [1, 'Pe\'ter', new Date()],
     function(err, result) {
        console.log(result[0].id);
        db.query('SELECT * FROM USERS WHERE Alias=?', ['Peter'], function(err, result) {
            console.log(result);
            db.detach();
    

    对于Node Firebird 库的完整概述,请使用内置测试模块 - 它突出显示了访问数据库的所有预期方法和所有典型错误。

    https://github.com/hgourvest/node-firebird/tree/master/test


    下一个罪魁祸首可能是await修饰符。

    根据https://ponyfoo.com/articles/understanding-javascript-async-await

    请注意,await 只能标有async 关键字的函数中使用。它的工作方式类似于生成器,在你的上下文中暂停执行,直到承诺解决

    函数被标记了吗?

    https://github.com/hgourvest/node-firebird/blob/master/lib/index.js

    Transaction.prototype.query = function(query, params, callback) {
    

    那么,它是用async标记的吗,这个函数是写成暂停容忍Promise-returning的方式吗?是不是。 Firebird-Node 库中是否还有其他函数用async 标志编写?我找不到。

    这意味着如果您想在异步等待离线模式下使用一些 Firebird-Node 代码,您必须创建自己的 async-aware 函数并在其中以通常的非async 模式调用数据库函数函数,并且只将您的特殊 async-ready 包装器传递给 await

    【讨论】:

      【解决方案3】:

      我重写了代码,只使用 node-firebird ......

      const firebird = require('node-firebird');
      const path = require('path');
      const moment = require('moment');
      
      class TestDB {
        constructor(folder) {
          this.options = {
            host: 'localhost',
            database: path.resolve(folder),
            user: 'SYSDBA',
            password: 'masterkey',
            port: 3050,
            lowercase_keys: false, 
            role: null,
            pageSize: 4096,
          };
        }
      
        getGlients = async () => {
          return new Promise((resolve, reject)=> {
            this.db.query('select * from t_client', (err, res) => {
              resolve(res);
            })
          })
        };
      
        connectDb = async () => {
          return new Promise((resolve, reject) => {
            firebird.attach(this.options, (err,db) => {
              resolve(db)
            });
          });
        };
      
        insertData = async() => {
          return new Promise((resolve, reject) => {
            this.db.execute(
              `insert into t_client 
               (t_client_id, 
                matricule,
                nom,
                prenom,
                nom_jeune_fille,
                date_naissance,
                rang_gemellaire,
                langue,
                sexe,
                maison,
                etage,
                chambre,
                lit,
                commentaire_individuel,
                commentaire_global,
                t_profil_remise_id,
                t_personne_referente_id,
                facturation,
                date_derniere_visite
                ) values (
                  4,
                  '000233532',
                  'NAME',
                  'NAME2',
                  'NAME3',
                  '19700504',
                  1,
                  'FR',
                  'M',
                  '',
                  '',
                  '',
                  '',
                  '',
                  '',
                  1,
                  1,
                  '1',
                  ''  
                )`
            , (err, res) => {
              if (err) reject(err);
              resolve(res);
            });
          })
      
      
        }
      
        launchTest = async () => {
          this.db = await this.connectDb();
          console.log(this.db)
          let rows = await this.getGlients();
          console.log(rows);
          try {
            const res = await this.insertData();
            console.log(res);
          } catch (error) {
            console.log(error);
          }
        };
      }
      
      export { TestDB };
      

      结果是一样的。

      【讨论】:

      • 你能在 NPM 模块中使用一些调试器吗?在node-firebirddoCallback 函数内设置断点,看看里面发生了什么。在第 1234 行,似乎在通过主要检查 if (obj instanceof Error) 而未触发后进行了一些次要检查 if (isError(obj)) ....。尝试在那里打开调试器并查看实际数据进入函数(有和没有 Electron - 可能存在差异)以及预期失败的地方
      • 对于我在源代码中看到的内容,它应该在obj.status 非零时触发,在我看来status 成员用于传输旧式 Firebird 错误代码( GDS 代码)。然而,第 1234 行显示 callback(new Error(obj.message)),因此丢失了 obj.status,并可能在缺少或非预期的 .message 值时产生二次错误
      • 1) 你可以尝试在 Firebird 2.5 上做同样的事情吗? 2) Electron 做一些额外的多线程吗?会不会是firebird连接是在一个线程中创建的,但请求是在其他线程中完成的?
      • 听说这个js包有新的FB3“有线协议”的问题,事实上已经废弃了,有人改用其他js包
      • 我解决了 :) 我将数据库操作移到了 MAIN 进程中。目前,我正在使用 IPC 通信。效果很好。
      猜你喜欢
      • 2012-03-04
      • 2012-08-29
      • 2021-01-17
      • 1970-01-01
      • 2018-03-21
      • 1970-01-01
      • 1970-01-01
      • 2018-11-14
      • 1970-01-01
      相关资源
      最近更新 更多