How can I insert objects in SQL Server running a function in a loop? ConnectionError: .connect can not be called on a Connection in `Connecting` state

How can I insert objects in SQL Server running a function in a loop? ConnectionError: .connect can not be called on a Connection in `Connecting` state

我在一个 NodeJS 项目中工作,这个项目我决定改变我做它的方式,因为这个 way 没有用,让我试着解释一下。

我需要将数据插入 SQL 服务器数据库,所以我做了一个函数 insertOffice() 这个函数使用 Tedious 打开一个连接,然后用数据将数据提取到 url从数组 data2 加载坐标,然后用这个坐标创建一个对象,然后将这个对象插入到数据库中。当仅插入我的 data2 数组的一部分时,它可以工作,仅通过 sendind data[0] 它添加:

{
  latjson: 1,
  lonjson: 1,
  idoficina: "1",
}

但我想插入数组的两个部分,将 data2[0] 更改为 data2[index],以便能够插入我的所有数组,因此我尝试创建另一个函数 functionLooper() 循环 insertOffice() 从我的数组 data2 中插入我的数据。 我构建了这个小代码来学习如何循环一个函数,它打印 index 这是我用来带来 idoficina.

的值

如您所见,functionLooper() 运行代码两次,因此它可以完整读取 data2 数组,我有这段使用相同逻辑工作的小代码,我使用它构建了我的完整代码:

function insertOffice(index) {
    console.log(index);
}

function functionLooper() {
    for (let i = 0; i < 5; i++) {
        let response = insertOffice(i);
    }
}

functionLooper();

这会打印:

0
1
2
3
4

所以我的代码应该发送 index

我期待我的代码循环我的 insertOffice() 并能够插入我的对象,问题是这似乎不起作用,因为我收到此错误:

C:\...\node_modules\tedious\lib\connection.js:993
      throw new _errors.ConnectionError('`.connect` can not be called on a Connection in `' + this.state.name + '` state.');
            ^

ConnectionError: `.connect` can not be called on a Connection in `Connecting` state.

这是我的代码:

var config = {
    ....
 };

const data2 = [
    ...
 ];

var connection = new Connection(config);

function insertOffice(index) {
    console.log(index)
    connection.on("connect", function (err) {
        console.log("Successful connection");
    });
    connection.connect();

    const request = new Request(
        "EXEC SPInsert @Data1, ... ",
        function (err) {
            if (err) {
                console.log("Couldn't insert, " + err);
            } else {
                console.log("Inserted")
            }
        }
    );
    console.log(myObject.Id_Oficina)
    request.addParameter("Data1", TYPES.SmallInt, myObject.Id_Oficina);
    request.on("row", function (columns) {
        columns.forEach(function (column) {
            if (column.value === null) {
                console.log("NULL");
            } else {
                console.log("Product id of inserted item is " + column.value);
            }
        });
    });
    request.on("requestCompleted", function () {
        connection.close();
    });
    connection.execSql(request);
}

function functionLooper() {
    for (let i = 0; i < 2; i++) {
        let response = insertOffice(i);
    }
}

functionLooper();

我不知道这是否是正确的方法(循环插入函数 insertOffice() 两次),如果您知道更好的方法,并且可以在示例中告诉我怎么做使用与我的代码类似的代码,将不胜感激。

您正在接近 asynchronous problem as if it's a synchronous one. You're also making your life a bit harder by mixing event based async tasks with promise based 个。

例如,connection.connect() 是异步的(意味着它不会在下一行代码执行之前完成所有工作),只有在 connection 发出 connect 事件。因此,在触发此事件之前,不应启动用于开始处理数据的触发器。

对于循环中的每个事件,它们不是 运行 一次一个,而是同时发生,因为 fetch() 是一个承诺(异步),它之前不会完成循环的下一次迭代。在某些情况下,它甚至可能在数据库连接准备就绪之前就已经完成,这意味着代码执行在与数据库的连接建立之前已经转移到数据库请求。

为了让您的代码尽可能易于管理,您应该以“承诺化”连接/请求为目标,这样您就可以编写一个完全基于承诺的程序,而不是混合承诺和事件(这将非常棘手管理 - 但有可能)。

例如:

const connection = new Connection(config);
// turn the connection event into a promise
function connect() {
 return new Promise((resolve, reject) => {
  connection.once('connect', (err) => err ? reject(err) : resolve(connection));
  connection.connect()
 });
}

// insert your data once the connection is ready and then close it when all the work is done
function insertOffices() {
  connect().then((conn) => {
    // connection is ready I can do what I want
    // NB: Make sure you return a promise here otherwise the connection.close() call will fire before it's done
  }).then(() => {
    connection.close();
  });
}

可以采用相同的方法来“承诺”插入。

// turn a DB request into a promise
function request(conn) {
  return new Promise((resolve, reject) => {
    const request = new Request(...);
    request.once('error', reject);
    request.once('requestCompleted', resolve);
    conn.execSql(request);
  });
}

然后可以将其组合起来执行一个循环,一次执行一个循环:

function doInserts() {
  return connect().then((conn) => {
    // create a "chain" of promises that execute one after the other
    let inserts = Promise.resolve();
    for (let i = 0; i < limit; i++) {
        inserts = inserts.then(() => request(conn));
    }
    return inserts;
  }).then(() => connection.close())
}

或并行:

function doInserts() {
  return connect().then((conn) => {
    // create an array of promises that all execute independently
    // NB - this probably won't work currently because it would need
    // multiple connections to work (rather than one)
    let inserts = [];
    for (let i = 0; i < limit; i++) {
        inserts.push(request(conn));
    }
    return Promise.all(inserts);
  }).then(() => connection.close())
}

我终于可以修复它了,我正在分享我的代码让每个人都可以使用它并进行多次插入,感谢 Dan Hensby,我没有按照他的方式去做,而是使用了他所说的部分内容,谢谢致 RbarryYoung 和 MichaelSun90,他们告诉我怎么做,我所做的就是改变我的

var connection = new Connection(config);

到 运行 我的

function insertOffice(index) { ... }

看起来像这样:

function insertOffice(index) {
    var connection = new Connection(config);
    ....
}