根据 API 请求失去与 SQL 服务器和节点的连接

Losing connection with SQL Sever and Node on API request

我正在尝试循环查询以获得给定大小的结果,但在我进行第一个查询后出现错误

我试图重新打开连接,它告诉我它已经打开,当我尝试只使用第一个连接时,它说它已关闭

axios.defaults.headers.common['X-API-KEY'] = apiKey;
axios.defaults.headers.common['Content-Type'] =  'application/json';
axios.defaults.baseURL = 'https://v2.namsor.com/NamSorAPIv2';

const selectStatment = "SELECT [CandidateId] AS id, ( CASE LEN(REPLACE([CandidateName],' ','')) WHEN LEN([CandidateName]) - 1 then PARSENAME(REPLACE([CandidateName],' ','.'), 2) ELSE PARSENAME(REPLACE([CandidateName],' ','.'), 3) END ) AS firstName, PARSENAME(REPLACE([CandidateName],' ','.'), 1) AS lastName ";
const cleanWherequery = 'WHERE NOT firstName IS NULL OR NOT firstName IS NULL ANd NOT lastName IS NULL';
const sqlTable = '##apiTable';
const tempQuery = `DROP TABLE IF EXISTS ##apiTable, ##clean; ${selectStatment} INTO ##clean FROM [dbo].[DimCandidate]; SELECT * INTO ${sqlTable} FROM ##clean ${cleanWherequery}`;
const orderByFetch= `ORDER BY lastName DESC OFFSET ${i * 100} FETCH NEXT 100`
const countQuery = `SELECT COUNT(*) AS Count FROM ${sqlTable}`

const conn = new sql.ConnectionPool(dbConfig);

conn.connect()
.then(function(){
  const reqCount = new sql.Request(conn);

  reqCount.query(`${countQuery}`)
  .then(function(recordset){
    let opt = recordset.recordset[0]['Count'];
    let segCount = Math.ceil(opt/100);
    console.log(segCount);
    return segCount;
    sql.close()
  })
  .then(function(count){
    conn.connect()
    .then(function(){
      const req = new sql.Request(conn);
      for(let i = 0; i < count; i++){
        req.query(`SELECT TOP 201 id, firstName, lastName FROM ${sqlTable} ${orderByFetch}`)
        .then(function (recordset) {
          for(i = 0; i < count; i++){
            console.info(recordset.recordset);
            const jsonSet = {
              'personalNames': recordset.recordset
            }
            console.log(jsonSet);
            getRace(jsonSet);
            getGender(jsonSet)
          }
        }).catch(e =>{
          console.log(e);
        })
      }
  })
}).catch(function (err) {
    console.log(err);
    conn.close();
  })
})
.then(function(){
  conn.close();
})
.catch(err => {
  console.log(err);
  conn.close()
})
.catch(function(e){
  console.log(e);
})

预期的结果是循环查询并发出 api 请求,当前问题是发出第二个查询

我进一步调查并找到了这个问题的答案——正如我所怀疑的那样,这是由于使用 promises 嵌套了单独的异步序列。

出现问题是因为代码创建了两个异步路径,一个在另一个中。您可能会认为外部异步路径等待内部路径完成,但事实并非如此 - 内部路径在外部路径中启动,但一旦启动,就会单独执行,而外部执行路径异步继续.

当使用具有 .then(...); 步骤的承诺时,请务必牢记处理承诺解析的函数现在位于单独的执行路径上,并且代码遵循 then(...);子句在承诺解决之前执行。

为了说明这一点,我创建了一个测试函数来阐明 OP 代码中的情况。代码的objective是执行五个步骤:

  1. 打开数据库连接
  2. 将数据加载到临时文件中 table
  3. 从临时文件读取数据table
  4. 上报数据
  5. 关闭数据库连接

问题的出现是因为,由于 .then(..) 承诺的嵌套,甚至在第 2 步完成之前就执行了第 5 步:

function TestLostConnection(){
    console.log( ">> START TestLostConnection")
    const loadTempTable = "IF OBJECT_ID('tempdb..##tempTable') IS NOT NULL DROP TABLE ##tempTable; SELECT TOP(1) * INTO ##tempTable from Sys_TestData; ";
    const readTempTable = "SELECT * FROM ##tempTable;"

    // Get connection pool from DB API
    const conn = darwinDB.newConnectionPool();

    // Open the connnection, then access the database
    console.log( "  ### STEP 1: Initiating async database access" );
    conn.connect().then( 
        function(){ 
            console.log( ">> START ASYNC SEGMENT #1" );

            // Get a new request from the connection pool
            let req = new sql.Request(conn);

            // Use request to load the temp table
            console.log( "  ### STEP 2: Running query to load temp table" );
            req.query( loadTempTable ).then(
                function(){

                    console.log( ">> START ASYNC SEGMENT #2 - temp table has been loaded" );

                    // Get new reqeuest from connection pool
                    console.log( "Getting new Request from connection pool");
                    let reqCount = new sql.Request(conn);

                    console.log( "  ## STEP 3: running query to read data from ##tempTable");
                    reqCount.query(readTempTable).then(

                        function(recordset){
                            console.log( ">> START ASYNC SEGMENT #3 - Read from ##tempTable complete" );

                            // Report the data loaded from ##tempTable
                            console.log( "  ## STEP 4: Reporting data to the console")
                            console.dir( recordset );

                            console.log( "<< END ASYNC SEGMENT #3");
                        }
                    )
                    .catch(function (err) {

                        console.log("#### CATCH A")
                        console.log(err);
                        conn.close();
                    })

                    console.log( "<< END ASYNC SEGMENT #2 " )
                }
            ).catch(err => {
                    console.log("#### CATCH B")
                    console.log(err);
                    conn.close()
                }
            )

            console.log("<< END ASYNC SEGMENT #1")
        }
    ).then(function(){
            console.log( ">> START ASYNC SEGMENT #4")
            console.log( "  ## STEP 5: CLOSING CONNECTION" );
            conn.close();
            console.log( "<< END ASYNC SEGMENT #4")
        }
    ).catch(err => {
            console.log("#### CATCH C")
            console.log(err);
            conn.close()
        }
    )

    console.log( "<< END TestLostConnection")

}

这是执行代码时的控制台输出:

>> START TestLostConnection
   ### STEP 1: Initiating async database access
<< END TestLostConnection
>> START ASYNC SEGMENT #1
  ### STEP 2: Running query to load temp table
<< END ASYNC SEGMENT #1
>> START ASYNC SEGMENT #4
  ## STEP 5: CLOSING CONNECTION
<< END ASYNC SEGMENT #4
#### CATCH B
{ ConnectionError: Connection not yet open.