簡體   English   中英

在接收 POST 數據之前,如何防止 Heroku 上部署的 NodeJS Web 應用程序退出?

[英]How do I keep a deployed NodeJS web app on Heroku from exiting before receiving POST data?

我在基於服務器的應用程序方面非常缺乏經驗(並且在客戶端應用程序方面經驗略多)。 但是,基於許多示例(主要是在 Stack Overflow 上),我創建了一個基本的 NodeJS Web 應用程序,它在本地運行時可以正常工作(例如“heroku local web”)。 但是在部署時,應用程序不會收到 POSTed 數據,除非我插入延遲。 我確定我做錯了什么,所以我希望有人能指出我處理這個問題的正確方法。 我已經將應用程序提煉到基本問題,仍然使用下面的代碼顯示。

基本上,據我所知,簡單的網頁將 JSON 數據發布到我的網絡應用程序。 Web 應用程序確實收到了 POST 消息。 但在 Web 應用程序可以收集正在傳輸的數據之前,Web 應用程序似乎已退出。 當應用在本地運行時,數據不會丟失(當我在 Google Cloud 上部署早期版本時不會丟失)。 但是在 Heroku(免費層)上部署時確實會發生損失。

使用其他幾種語言的經驗讓我很困惑,為什么 NodeJS 應用程序在收到任何消息之前並不總是退出,因為應用程序中沒有代碼來延遲退出(例如消息泵或等待退出信號)。 當它奏效時,我只是聳了聳肩,並決定有一些魔法在起作用,我稍后會了解。 但實際上,我所看到的失敗對我來說更有意義。

無論如何,正是這種懷疑導致我添加了延遲(下面顯示的添加行帶有 //*** 注釋)。 從中我能夠確定數據正在到達,但沒有被收集,沒有延遲。

下面是主要的代碼文件。 在這些下面是一些日志,顯示了添加延遲前后的本地和遠程行為。

任何幫助表示贊賞。

索引.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>

服務器.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

萬一后來有人遇到這個問題,我沒有得到任何反饋,也找不到合理的解決方法。 (我嘗試了 promises 和其他一些臨時信令。)所以我通過使用 Express 作為我的服務器來回避這個問題,因為我知道這已在全球范圍內成功部署。 考慮到極其簡單的數據傳輸,切換是微不足道的,而且工作正常。 (我打算深入研究 Express 源代碼,看看他們是如何處理它的,但似乎將它包含在我的 NodeJS 應用程序中會導入一些超過 200 個其他包的內容,因此很難深入挖掘。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM