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

Node.js SOAP服务器:如何从Promise异步操作返回正确数据?

Node.js SOAP服务异步Promise返回数据问题解决

问题场景

基于Node.js搭建的SOAP服务器,调用异步Promise函数操作Oracle数据库,尝试用XMLWriter构建包含查询结果的XML响应,但客户端仅收到空的<result/>元素,无法获取数据库查询添加的子元素。核心代码如下:

const soap = require('soap');
const http = require('http');
const XMLWriter = require('xml-writer');

const service = {
   ImpDispatcherService: {
      ImpDispatcher: {
         performTest: function (args) {
            const xw = new XMLWriter(true);
            xw.startDocument();
            xw.startElement('result');
            queryDatabase(args.parameter1, xw).then(success => {
               console.log(success);
               xw.endDocument();
               console.log(xw.toString()); // -> prints the full XML-File
            });             
            return { testResult: xw.toString() };
         }
      }
   }
};

var server = http.createServer((request, response) => {
   response.end('404: Not Found: ' + request.url);
});

// Create the SOAP server
const xml = require('fs').readFileSync(`${__dirname}/ImpDispatcherService.wsdl`, 'utf8');
var server = http.createServer((request, response) => {
   response.end('404: Not Found: ' + request.url);
});

server.listen(8000, 'localhost');
soap.listen(server, '/imp', service, xml, () => {
   logger.info('Server initialized');
});

async function queryDatabase(pars) {
   const oracledb = require('oracledb');
   const connection = await oracledb.getConnection(db);
   const result = await connection.execute(`BEGIN :ret := getResult(${pars}); END;`, {ret: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR } });
   let row;
   while (row = await result.outBinds.ret.getRow()) {
      xw.writeElement('tag', row.blabla);
   }

   return true;
}

问题原因

performTest方法调用queryDatabase后直接返回xw.toString(),此时异步数据库查询尚未完成,XMLWriter还未添加任何子元素,因此返回的是仅包含空<result/>标签的XML字符串。

解决方案

将performTest改为异步函数,等待queryDatabase执行完成后再构建并返回响应数据,同时修正queryDatabase的参数传递问题:

修改后的核心代码

const service = {
   ImpDispatcherService: {
      ImpDispatcher: {
         // 改为async函数,支持await异步操作
         performTest: async function (args) {
            const xw = new XMLWriter(true);
            xw.startDocument();
            xw.startElement('result');
            // 等待数据库查询完成再继续
            await queryDatabase(args.parameter1, xw);
            xw.endDocument();
            return { testResult: xw.toString() };
         }
      }
   }
};

// 修正queryDatabase,接收xw参数并完成数据库操作
async function queryDatabase(pars, xw) {
   let connection;
   try {
      const oracledb = require('oracledb');
      connection = await oracledb.getConnection(db);
      const result = await connection.execute(`BEGIN :ret := getResult(${pars}); END;`, {ret: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR } });
      let row;
      while (row = await result.outBinds.ret.getRow()) {
         xw.writeElement('tag', row.blabla);
      }
      // 关闭数据库游标
      await result.outBinds.ret.close();
   } finally {
      // 确保数据库连接关闭,避免资源泄漏
      if (connection) {
         await connection.close();
      }
   }
   return true;
}

关键修改点

  • 将performTest声明为async函数,使用await等待queryDatabase执行完毕,保证XMLWriter完成所有子元素写入后再返回结果。
  • 为queryDatabase补充xw参数,确保能正确向XMLWriter添加数据库查询到的子元素。
  • 添加try/finally块,确保数据库连接和游标在操作完成后关闭,避免资源泄漏。
  • 移除原代码中重复定义的http.createServer实例。

完整修改后代码

const soap = require('soap');
const http = require('http');
const XMLWriter = require('xml-writer');
const oracledb = require('oracledb');

// 数据库配置,需根据实际情况填写
const db = {
  user: 'your_db_user',
  password: 'your_db_password',
  connectString: 'your_db_connect_string'
};

const service = {
   ImpDispatcherService: {
      ImpDispatcher: {
         performTest: async function (args) {
            const xw = new XMLWriter(true);
            xw.startDocument();
            xw.startElement('result');
            await queryDatabase(args.parameter1, xw);
            xw.endDocument();
            return { testResult: xw.toString() };
         }
      }
   }
};

// 创建HTTP服务器
const server = http.createServer((request, response) => {
   response.end('404: Not Found: ' + request.url);
});

// 读取WSDL文件
const xml = require('fs').readFileSync(`${__dirname}/ImpDispatcherService.wsdl`, 'utf8');

// 启动服务器并监听SOAP请求
server.listen(8000, 'localhost');
soap.listen(server, '/imp', service, xml, () => {
   console.info('Server initialized');
});

async function queryDatabase(pars, xw) {
   let connection;
   try {
      connection = await oracledb.getConnection(db);
      const result = await connection.execute(`BEGIN :ret := getResult(${pars}); END;`, {ret: { dir: oracledb.BIND_OUT, type: oracledb.CURSOR } });
      let row;
      while (row = await result.outBinds.ret.getRow()) {
         xw.writeElement('tag', row.blabla);
      }
      await result.outBinds.ret.close();
   } catch (err) {
      console.error('Database query error:', err);
      throw err; // 抛出错误让SOAP框架处理异常响应
   } finally {
      if (connection) {
         await connection.close();
      }
   }
   return true;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 00:06:00