0

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

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

以下是来自 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 信息返回 - console.log(John doe's info) SOAP RESPONSE = empty

点击按钮两次 console.log(John doe's info) SOAP RESPONSE = John doe's info

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

console.log 每次都有效:

我是否有 global.results 值具有竞争条件的范围问题???

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

我是否错误地传递给了肥皂服务器的回调?

callback({
            contracts: global.results
         });

任何见解将不胜感激。

4

1 回答 1

1

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

.then你的 Promise和块中的所有代码.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
  });
于 2016-02-10T23:39:21.307 回答