Node JS Soap Server(node-soap)从postgres回调传递值

Node JS Soap Server(node-soap) passing values from postgres callback

我有一个问题,我正在使用 node-soap 和 pg-promise。我有一个问题,当我向 soap 服务发出请求时,响应被延迟,换句话说,我必须在响应返回之前发送两次请求(使用 soap ui):

我想知道我是否没有将来自数据库调用的响应正确传递给节点 soap 回调:

以下是来自 node-soap 网站的示例代码:

var myService = {
    MyService: {
        MyPort: {
            MyFunction: function(args) {
              return {
                  name: args.name
              };
            },

            // This is how to define an asynchronous function.
            MyAsyncFunction: function(args, callback) {
              // do some work
              callback({
                  name: args.name
              });
            },

            // This is how to receive incoming headers
            HeadersAwareFunction: function(args, cb, headers) {
              return {
                  name: headers.Token
              };
            },

            // You can also inspect the original `req`
            reallyDeatailedFunction: function(args, cb, headers, req) {
              console.log('SOAP `reallyDeatailedFunction` request from  + req.connection.remoteAddress);
              return {
                  name: headers.Token
              };
            }
        }
    }
};

var xml = require('fs').readFileSync('myservice.wsdl', 'utf8'),
server = http.createServer(function(request,response) {
  response.end("404: Not Found: " + request.url);
});

这是我的代码:

                        var http = require('http');
                        var soap = require('soap');
                        global.results = '';


                        var promise = require('bluebird'); // 
                        var options = {
                        promiseLib: promise // switch to bluebird lib
                    };

                    // Database connection details;
                    var cn = {
                        host: '',
                        port: 5432,
                        database: '',
                        user: '',
                        password: ''
                    };


                       var pgp = require('pg-promise')(options);

                       var db = pgp(cn);


                       var cancelService = {
                        cancelService: {
                            Cancel_PortType: {
                                getAgreement: function(args,callback,headers) {


                                    var values = {
                                            vin: args.vin
                                    };

                                    db.any("select contract_num as contract, " +
                                        "CASE WHEN sg_con_status='A' THEN 'Active ' " +
                                        "WHEN sg_con_status='X' THEN 'Expired' " +
                                        "WHEN sg_con_status='C' THEN 'Cancelled' " +
                                        "END AS agreementStatus, " +
                                        "tfs_product_type as productType, " +
                                        "vin, cust_first_name as customerFirstName,    cust_last_name as customerLastName," +
                                        "TO_CHAR(original_busdate,'YYYY-MM-DD') as purchaseDate,   TO_CHAR(expire_date,'YYYY-MM-DD') as expirationDate " +
                                        "from tfs_contract_summary, sg_con_m1 where sg_con_m1.sg_con_contract = tfs_contract_summary.contract_num " +
                                        " AND vin = ${vin}",values)

                                    .then(function(data) {

                                    //set value of DB return to global
                                         global.results = data;

                                        console.log("DATAAAAAAA:", data);

                                    })


                                    .catch(function(error) {
                                            console.log("ERROR:", error); // print the error;
                                        })
                                        .finally(function() {

                                            pgp.end(); //closing the connection pool.

                                        });


                                    //  }



                                    callback({
                                        contracts: global.results
                                    });
                                }
                            }
                        }
                    }
                    var xml = require('fs').readFileSync('CancelService.wsdl', 'utf8'),
                        server = http.createServer(function(request, response) {
                            response.end("404: Not Found: " + request.url)


                        });


                    server.listen(8000);
                    soap.listen(server, '/wsdl', cancelService, xml);

每次我在 SOAPUI 中发出请求时,我的所有 console.log() 都会显示返回的数据,但直到我第二次发送请求时才会返回响应:

例如

点击按钮一次: vin = 12312364812736498

我希望 John doe 的信息 return - console.log(李四的信息) SOAP 响应 = 空

点击按钮两次 console.log(李四的信息) SOAP RESPONSE = John doe 的信息

如果我使用提供的 soap 客户端示例代码并发出请求:

console.log 每次都有效:

我是否遇到 global.results 值存在竞争条件的范围问题???

我很确定我的代码可能有问题,因为我是 Node JS 等方面的新手...

我是否错误地传递给了 soap-server 的回调?

callback({
            contracts: global.results
         });

如有任何见解,我们将不胜感激。

我认为问题在于您在设置 global.results 之前调用回调函数(即使它位于函数的底部)。

你的 promise 的 .then.catch 中的所有代码异步阻塞 运行 - 这意味着它们被拖到事件循环中 运行 之后;当前代码完成后。

这是您的代码中发生的顺序:

  1. 您启动了一个异步发生的数据库查询
  2. 你打电话给callback({contracts: global.results})。此时,global.results未定义。
  3. 您的数据库查询完成,事件循环根据需要执行 .thens 和 .catches。这是你设置 global.results 的地方(当然太晚了)
  4. 您向服务发出另一个请求 - 这次,global.results 已设置为上次查询的结果。

解决方案是忘记使用 global 并将回调放在您的承诺的 .then 中:

db.any("my_awesome_sql")
  .then(function(data) {
    console.log("DATAAAAAAAA!!!", data);
    callback({contracts: data});
  })
  .catch(function(error) {
    // Handle error
  })
  .finally(function() {
    // Cleanup
  });