javascript - 使用 Express 从本地主机获取数据/将数据写入本地主机

标签 javascript jquery html node.js express

我正在尝试使用 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 - 示例:
Deploy to Heroku

原始答案

您的代码几乎没有问题:

  1. 你没有检查错误
  2. 你正在使用阻塞函数
  3. 你隐含地依赖文件权限,但你没有检查它
  4. 您正在使用字符串连接而不是 path.join 来连接路径
  5. 您不断轮询新数据,而不是等待它发生变化
  6. 您没有捕获可能引发异常的函数异常
  7. 您没有等待异步操作完成,也没有处理错误

您现在遇到的主要问题很可能与文件权限有关。好消息是您不需要任何文件访问权限来执行您正在做的事情,并且为此使用文件也不是最佳选择。如果您不需要它,您只需将颜色存储在一个变量中,它会在服务器重启之间持续存在 - 即使您这样做,我也会为此使用一个简单的数据库。

例如:

// 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 而不是 /messageBody =... 但您可以根据需要轻松更改它 - 见下文。

服务器代码 - 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 上并自行测试:

Deploy to Heroku

享受吧。

关于javascript - 使用 Express 从本地主机获取数据/将数据写入本地主机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43499382/

相关文章:

javascript - 如何使用 ng-repeat 将 JSON 响应映射到 Html 页面

javascript - 关于 iPhone 旋转时 HTML 的问题

javascript - 在 HTML 中显示日志并显示缩进的更好方法是什么?

javascript - react Excel 工作簿构建

php - WordPress 表格的 jQuery UI 自动完成

javascript - ASP.NET MVC Web API 使用 jQuery Ajax 删除调用,数据参数不起作用

javascript - 具有相同名称的多个按钮显示不同的 div

javascript - 在 TypeScript 中使用可选参数调用函数

javascript - D3 沿路径停止并重新启动过渡,以允许点击到地理数据坐标

javascript - “被 CORS 策略阻止”,但存在 header