我正在尝试使用 Node (w/npm)和 express 为网络艺术类(class)创建一个网络应用程序。这个想法是让网站的主体全部为一种颜色,但任何人都可以在 Twilio 数字处向网站发送十六进制代码/CSS 颜色,网站的颜色将立即更改为该颜色值。
从本质上讲,它的工作原理是服务器在 http://example.com/message 收到来自 Twilio 的 POST 请求。 ,其中包含短信的正文。它将它写入位于 ~/app/.data/color.tmp 的临时文件,客户端可以通过调用 jQuery .get() 来访问 http://example.com/color。 , 返回
所以这就是问题所在:我有一个在 glitch.me 上运行的应用程序版本,所以我知道这段代码可以运行,但我在让它在我的域上运行时遇到了很多麻烦。我安装了该应用程序并可以使用 npm 启动它,它成功地向我显示了 HTML 页面,但是 Chrome devtools 显示脚本在尝试访问/color 时收到 403。此外,我网站的新文本不会更改/.data/color.tmp 中的颜色值。我认为这可能是权限问题,但我检查了它们,它们似乎没问题。
这是 index.html 页面上的服务器文件和脚本:
app/server.js
var express = require('express');
var bodyParser = require('body-parser');
var fs = require('fs');
var app = express();
app.use(bodyParser.urlencoded({extended: false}));
var dataPath = '.data/color.tmp';
// set a new color (saves posted color to disk)
app.post("/message", function (request, response) {
var dataStr = JSON.stringify(request.body.Body);
fs.writeFile(dataPath, dataStr);
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
var dataStr = fs.readFileSync(dataPath).toString();
response.send(JSON.parse(dataStr));
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
app/views/index.html
<script>
// checks server for color value and sets background
function checkForColorChange() {
$.get('/color', function getColorComplete(data) {
document.body.style.backgroundColor = data;
console.log(data);
})
}
// Poll the server at 2000ms interval
setInterval(checkForColorChange, 2000);
checkForColorChange();
</script>
无论如何,如果它在 Glitch 上如此轻松地工作并且不会在我的网站上工作,我觉得我一定错过了一些非常明显的东西,但我已经被困了几天而且没有取得任何进展!任何帮助将不胜感激。如果还有任何不清楚的地方,请告诉我。
最佳答案
(有关工作示例,请参阅下面的更新)
TL;DR - 示例:
原始答案
您的代码几乎没有问题:
- 你没有检查错误
- 你正在使用阻塞函数
- 你隐含地依赖文件权限,但你没有检查它
- 您正在使用字符串连接而不是
path.join
来连接路径 - 您不断轮询新数据,而不是等待它发生变化
- 您没有捕获可能引发异常的函数异常
- 您没有等待异步操作完成,也没有处理错误
您现在遇到的主要问题很可能与文件权限有关。好消息是您不需要任何文件访问权限来执行您正在做的事情,并且为此使用文件也不是最佳选择。如果您不需要它,您只需将颜色存储在一个变量中,它会在服务器重启之间持续存在 - 即使您这样做,我也会为此使用一个简单的数据库。
例如:
// some initial value:
var color = '#ffffff';
app.post("/message", function (request, response) {
var color = request.body.Body;
response.end();
});
// get the saved color (reading from disk)
app.get("/color", function (request, response) {
response.send(color);
});
app.get("/", function (request, response) {
response.sendFile(__dirname + '/views/index.html');
});
var listener = app.listen(process.env.PORT, function () {
console.log('listening on port ' + listener.address().port);
});
这是我要使用的第一个更改 - 不要依赖文件系统、权限、竞争条件等。
您的代码遇到的另一个问题是在请求处理程序中使用阻塞函数。除了事件循环的第一个 tick 之外,您永远不应该使用任何阻塞函数(名称中带有“Sync”的函数)。
我要做的另一项改进是使用 WebSocket 或 Socket.io,而不是定期轮询数据。这将很容易编码。有关示例,请参见此答案:
这样做的一个好处是,您的所有学生都会立即同时改变颜色,而不是在 2 秒的随机时刻改变颜色。
更新
我写了一个我上面描述的例子。
POST 端点略有不同 - 它使用 /color
路由和 color=#abcdef
而不是 /message
和 Body =...
但您可以根据需要轻松更改它 - 见下文。
服务器代码 - server.js:
// requires removed for brevity
const app = express();
const server = http.Server(app);
const io = socket(server);
let color = '#ffffff';
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/', express.static(path.join(__dirname, 'html')));
io.on('connection', (s) => {
console.log('Socket.io client connected');
s.emit('color', color);
});
app.post('/color', (req, res) => {
color = req.body.color;
console.log('Changing color to', color);
io.emit('color', color);
res.send({ color });
});
server.listen(3338, () => console.log('Listening on 3338'));
HTML 页面 - index.html:
<!doctype html>
<html lang=en>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width, initial-scale=1">
<title>Node Live Color</title>
<link href="/style.css" rel=stylesheet>
</head>
<body>
<h1>Node Live Color</h1>
<script src="/socket.io/socket.io.js"></script>
<script src="/script.js"></script>
</body>
</html>
样式表 - style.css:
body {
transition: background-color 2s ease;
background-color: #fff;
}
客户端 JavaScript - script.js:
var s = io();
s.on('color', function (color) {
document.body.style.backgroundColor = color;
});
特别有趣的是客户端代码非常简单。
对于您的原始端点,请在 server.js 中使用它:
app.post('/message', (req, res) => {
color = req.body.Body;
console.log('Changing color to', color);
io.emit('color', color);
res.end();
});
GitHub 上提供了完整示例:
我在本地和 Heroku 上对其进行了测试。您可以单击此按钮将其部署到 Heroku 上并自行测试:
享受吧。
关于javascript - 使用 Express 从本地主机获取数据/将数据写入本地主机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43499382/