【问题标题】:Multiple calls to web services from Node.js从 Node.js 多次调用 Web 服务
【发布时间】:2017-08-02 19:27:46
【问题描述】:

我正在构建一个原型 Web 应用程序,它响应带有查询参数的 GET 请求,并调用 3 个不同的 Web 服务,它们都具有不同的有效负载 - 2 个是 ReST(一个返回二进制对象、图像, 一个返回 JSON), 1 是 SOAP。

然后我需要将这些数据中的每一个组合成一个 HTML 页面,该页面为原始 GET 请求返回。

我是异步编程的新手,我认为这就是我出错的地方。

对于我正在使用的 SOAP

var locationRequest = require('request');        
locationRequest(options1, function (error, response, output) {
...
}

对于 ReST 调用,我使用了两个类似的调用,如下所示:

    var resourceJSON;
    var body2;
    var resourceHttp = require("https");          
    var resourceRequest = resourceHttp.request(resourceOptions, function (resourceRes) {
        var chunks2 = [];        
        resourceRes.on("data", function (chunk2) {
            body2 += chunk2;
        });
        resourceRes.on("end", function () {                
            resourceJSON = JSON.parse(body2);
        });
        resourceRes.on('error', function (error) {
            console.log('\n Error received: ' + error);
    });
    resourceRequest.end();
});

这些都发生在 Express app.get 中,即

app.get('/myURL', function(req,res,next){
}

因此,我需要做的最后一件事是组装这些响应并将一些 HTML 包括数据返回给调用者。
首先,我有一些(菜鸟,我敢肯定)变量范围的怪异。例如,如果我在 app.get 块的开头定义一个变量来保存来自 ReST 调用的 JSON,然后在 resourceRes.on("data...) 函数中写入它,我会收到一条消息,它是如果我在 app.et 块的末尾引用它,则未定义。

其次,由于这些调用都是异步启动的,在将数据组装到我的 HTML 响应之前,我如何确定所有调用都已完成?

非常感谢任何指导或帮助!

编辑

因此,我已将其简化为尽可能简单,因为我遇到了一个问题,当我从浏览器提交请求以启动进程时,浏览器只是等待“等待本地主机”然后最终因套接字超时错误而失败。如果我通过 Postman 提交请求,我会得到预期的 JSON 响应。有什么线索吗?

现在的代码如下所示:

app.get('/myurl', function(req,res,next){
var device = req.query.deviceId;
var resourceOptions = {
    "method": "GET",
    "hostname": "myhostname",
    "port": 443,
    "path": "/mypath/",
    "headers": {
        "authorization": "Basic HIDINGTHIS",
        "cache-control": "no-cache",
        "content-type": "application/json",      
    }
};

const resourceHttp = require("https");
const restRequest = () => {
    const promise = new Promise((resolve, reject) => {
        resourceHttp.request(resourceOptions, function (resourceRes) {
            var response = '';
            resourceRes.on("data", function (chunk2) {
                console.info('in on');  
                response += chunk2;
            });
            resourceRes.on("end", function () {
                console.info('in end');
                resolve(JSON.parse(response));
            });
            resourceRes.on('error', function (error) {
                console.info("in error");
                reject(error);
            });
            resourceRequest.end();
        });
    });
    return promise;
};

return restRequest()
.then(data => {
    // Send positive response from server
    console.info("succcess");
    res.end("DONE!");
})
.catch(err => {
    // Send negative response from server as there is an error
    console.info("error");
    res.end("ERROR!");
});     

});

【问题讨论】:

    标签: javascript node.js rest asynchronous soap


    【解决方案1】:

    您可以将它们包装在 Promise 中,然后在它们全部返回后使用 Promise.all() 运行代码:

    app.get('/myURL', function(req, res, next){
        var soapPromise = new Promise(function(resolve, reject) {
            locationRequest(options1, function(error, response, output) {
                if (error) reject(error);
                else resolve(response);
            })
        });
        var restPromise = new Promise(function(resolve, reject) {
            resourceHttp.request(resourceOptions, function(resourceRes) {
                var body = '';
                resourceRes.on("data", function (chunk) {
                    body += chunk;
                });
                resourceRes.on("end", function () {
                    resolve(JSON.parse(body));
                });
                resourceRes.on('error', function (error) {
                    console.log('\n Error received: ' + error);
                    reject(error);
                });
                resourceRequest.end();
            });
        });
        Promise.all([soapPromise, restPromise])
            .then(function([soapResult, restResult]) {
                //respond to client
            })
            .catch(function(error) {
                //catch an error generated from either request
            })
    })
    

    【讨论】:

    • 谢谢 - 在 Promise.all 函数中,您在示例中使用了 soapResult 和 restResult。它们是在请求块范围之外定义的变量,然后我在其中填充吗?
    • 它们是两个承诺所解决的任何问题。所以在这种情况下,第一个 promise 调用 resolve(response),第二个调用 resolve(JSON.parse(body))。这意味着他们将存储第一个回调中的任何响应以及第二个回调中的任何 JSON.parse(body)。
    【解决方案2】:

    你可以使用promise、.then().catch()如下:

      const locationRequest = require('request');
      const resourceHttp = require("https");
    
      const soapRequest = () => {
        const promise = new Promise((resolve, reject) => {
          locationRequest(options1, function (error, response, output) {
            if(error)
              reject(error);
            else
              resolve(response);
          });
        });
        return promise;
      };
    
      const restRequest = () => {
        const promise = new Promise((resolve, reject) => {
          resourceHttp.request(resourceOptions, function (resourceRes) {
            var response = '';
            resourceRes.on("data", function (chunk2) {
              response += chunk2;
            });
            resourceRes.on("end", function () {
              resolve(JSON.parse(response));
            });
            resourceRes.on('error', function (error) {
              reject(error);
            });
            resourceRequest.end();
          });
        });
        return promise;
      };
    
      return soapRequest()
        .then(restRequest)
        .then(data => {
          // Send positive response from server
    
        })
        .catch(err => {
          // Send negative response from server as there is an error
    
        });
    

    【讨论】:

    • 不过这些不会并行运行
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 1970-01-01
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多