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