在接收POST数据之前,如何阻止Heroku上已部署的NodeJS Web应用程序退出?

问题描述 投票:0回答:1

我对基于服务器的应用程序非常缺乏经验(而且对客户端应用程序的经验只有一点点经验)。但是,基于许多示例(主要是在Stack Overflow上),我创建了一个基本的NodeJS Web应用程序,该应用程序在本地运行时可以正常运行(例如“ heroku本地网络”)。但是,在部署时,除非插入延迟,否则该应用程序不会接收到POST数据。我确定自己做错了,所以我希望有人可以指出正确的处理方式。我将应用程序精简为基本问题,仍然使用下面的代码显示。

基本上,据我了解,简单的网页将JSON数据发布到我的Web应用程序中。 Web应用程序确实收到POST消息。但是在Web应用程序可以收集正在传输的数据之前,Web应用程序似乎已退出。当应用在本地运行时,数据不会丢失(当我在Google Cloud上部署早期版本时,数据也不会丢失)。但是,将其部署在Heroku(免费)上时,确实会造成损失。

[使用其他几种语言的经验让我感到困惑,为什么NodeJS应用程序在接收到任何消息之前并不总是退出,因为该应用程序中没有代码来延迟退出(例如消息泵或等待退出信号)。当它起作用时,我耸了耸肩,认为游戏中存在一些魔术,我以后会学习。但实际上,我看到的失败对我来说更有意义。

无论如何,正是这种怀疑导致我增加了延迟(以下显示的行带有// ***的注释)。据此,我能够毫无延迟地确定数据正在到达但未被收集。

下面是主要代码文件。在这些记录下有一些日志,显示了添加延迟之前和之后的本地和远程行为。

感谢任何帮助。

index.html:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang='en'>
<meta http-equiv='Content-Language' content='en'>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>

<script>

var scriptlocation = location.href.replace(document.location.pathname, '');
var request = new XMLHttpRequest();

function OnReadyStateChange() {
  if (request.readyState == 4 && request.status == 200) {
    console.log("Data upload complete.");
  }
}

function SendDataToServer(data) {
  var url = scriptlocation + "/server.js";
  request.open('POST', url, true);
  request.setRequestHeader('Content-type', 'application/json');
  request.onreadystatechange = OnReadyStateChange;
  request.send(data);
}

function SendEntryDataToServer() {
  var entryData = {
    fruit: "apple",
    size: "medium",
    color: "red"
  };
  console.log("*** SENDING DATA TO SERVER ***");
  var postData = JSON.stringify(entryData);
  SendDataToServer(postData);
  return false;
}

</script>
</head>
<body>
  <form>
    <input type="button" onclick="SendEntryDataToServer()" value="Post Data"/>
  </form>
</body>

server.js:

const http = require('http');
const fs = require('fs');

var server = http.createServer(
  function (req, res) {
    console.log(`req.url: ${req.url}\n`);

    if (req.method == 'POST') {
      console.log("POST");

      var body = '';

      req.on('data', function (data) {
        body += data;
      });

      req.on('end', function (data) {
        console.log(JSON.parse(body));
      });

      res.writeHead(200, {'Content-Type': 'text/html'});
      res.end('post received');

      console.log("Sleeping 5 seconds"); // ***
      setTimeout(function(){             // ***
        console.log("POST end");
      }, 5000);                          // ***
    } else {
      console.log("GET");

      fs.readFile('./' + req.url, function(err, data) {
        if (!err) {
          var dotoffset = req.url.lastIndexOf('.');
          var mimetype = dotoffset == -1
                        ? 'text/plain'
                        : {
                          '.html' : 'text/html',
                          '.ico' : 'image/x-icon',
                          '.jpg' : 'image/jpeg',
                          '.png' : 'image/png',
                          '.gif' : 'image/gif',
                          '.css' : 'text/css',
                          '.js' : 'text/javascript'
                        }[ req.url.substr(dotoffset) ];
          res.setHeader('Content-type' , mimetype);
          res.end(data);
        } else {
          console.log ('file not found: ' + req.url);
          res.writeHead(404, "Not Found");
          res.end();
        }
      });
    }
  }
);

const PORT = process.env.PORT || 5000;
server.listen(PORT, () => {
  console.log(`Server is running (port: ${PORT})...`);
});

console.log("FILE end");

添加延迟前的本地:

10:24:00 PM web.1 |  FILE end
10:24:00 PM web.1 |  Server is running (port: 5000)...
10:24:14 PM web.1 |  req.url: /index.html
10:24:14 PM web.1 |  GET
10:24:18 PM web.1 |  req.url: /server.js
10:24:18 PM web.1 |  POST
10:24:18 PM web.1 |  POST end
10:24:18 PM web.1 |  { fruit: 'apple', size: 'medium', color: 'red' }

在添加延迟之前部署:

2019-12-18T04:31:52.835329+00:00 app[web.1]: FILE end
2019-12-18T04:31:52.837439+00:00 app[web.1]: Server is running (port: 17378)...
2019-12-18T04:32:14.929250+00:00 heroku[router]: at=info method=GET path="/index.html" host=****.herokuapp.com request_id=**** fwd="*.*.*.*" dyno=web.1 connect=0ms service=9ms status=200 bytes=1233 protocol=https
2019-12-18T04:32:14.925381+00:00 app[web.1]: req.url: /index.html
2019-12-18T04:32:14.925407+00:00 app[web.1]:
2019-12-18T04:32:14.925509+00:00 app[web.1]: GET
2019-12-18T04:32:25.004774+00:00 app[web.1]: req.url: /server.js
2019-12-18T04:32:25.004809+00:00 app[web.1]:
2019-12-18T04:32:25.004964+00:00 app[web.1]: POST
2019-12-18T04:32:25.006023+00:00 app[web.1]: POST end

添加延迟后的本地:

10:48:04 PM web.1 |  FILE end
10:48:04 PM web.1 |  Server is running (port: 5000)...
10:48:08 PM web.1 |  req.url: /index.html
10:48:08 PM web.1 |  GET
10:48:12 PM web.1 |  req.url: /server.js
10:48:12 PM web.1 |  POST
10:48:12 PM web.1 |  Sleeping 5 seconds
10:48:12 PM web.1 |  { fruit: 'apple', size: 'medium', color: 'red' }
10:48:17 PM web.1 |  POST end

添加延迟后部署:

2019-12-18T04:51:50.925802+00:00 app[web.1]: req.url: /index.html
2019-12-18T04:51:50.925831+00:00 app[web.1]:
2019-12-18T04:51:50.925944+00:00 app[web.1]: GET
2019-12-18T04:51:56.071684+00:00 heroku[router]: at=info method=POST path="/server.js" host=****.herokuapp.com request_id=**** fwd="*.*.*.*" dyno=web.1 connect=0ms service=6ms status=200 bytes=151 protocol=https
2019-12-18T04:51:56.064644+00:00 app[web.1]: req.url: /server.js
2019-12-18T04:51:56.064659+00:00 app[web.1]:
2019-12-18T04:51:56.068033+00:00 app[web.1]: POST
2019-12-18T04:51:56.069013+00:00 app[web.1]: Sleeping 5 seconds
2019-12-18T04:51:56.075197+00:00 app[web.1]: { fruit: 'apple', size: 'medium', color: 'red' }
2019-12-18T04:52:01.073243+00:00 app[web.1]: POST end
node.js http post heroku web-applications
1个回答
0
投票

如果以后有人遇到此问题,我对此没有任何反馈,也无法真正找到合理的解决方法。 (我尝试了Promise和其他一些临时的信号。)因此,我知道使用Express作为我的服务器,从而在全球范围内成功部署了这一点。鉴于数据传输极为简单,切换非常简单,而且效果很好。 (我打算深入研究Express源,以了解他们如何处理它,但是似乎将它包含在我的NodeJS应用程序中导入了200多个其他程序包,因此实在是不鼓励使用。)

© www.soinside.com 2019 - 2024. All rights reserved.