使用Express

时间:2017-04-19 14:59:37

标签: javascript jquery html node.js express

我正在尝试使用node(w / npm)和express为web艺术类创建一个webapp。我们的想法是让网站的主体都是一种颜色,但是任何人都可以在Twilio号码上为网站发送十六进制代码/ CSS颜色,并且网站的颜色会立即变为该颜色值。

基本上它是如何工作的是服务器从http://example.com/message的Twilio接收POST请求,其中包含文本消息的正文。它将它写入〜/ app / .data / color.tmp中的临时文件,客户端使用jQuery .get()调用http://example.com/color来访问该文件,该文件返回

所以这就是问题所在:我得到了一个应用于glitch.me的应用程序版本,所以我知道这个代码可以工作,但是我在使用它在我的域上工作时遇到了很多麻烦。我安装了应用程序并可以使用npm启动它,它成功地向我显示了HTML页面,但Chrome devtools显示脚本在尝试访问/着色时正在接收403。此外,我的网站的新文本不会更改/.data/color.tmp中的颜色值。我认为这可能是一个权限问题,但我检查了它们,看起来很好。

这是index.html页面上的服务器文件和脚本:

应用/ 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);
});

应用/视图/ 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上如此容易,而且不会在我的网站上,但我已经被困了几天而且没有取得任何进展!任何帮助都会非常感激。如果有什么不清楚,请告诉我。

2 个答案:

答案 0 :(得分:1)

(有关工作示例,请参阅下面的更新)

TL; DR - 示例:
Deploy to Heroku

原始答案

您的代码几乎没有问题:

  1. 您没有检查错误
  2. 您正在使用屏蔽功能
  3. 你隐含地依赖文件权限,但你没有检查它
  4. 您正在使用字符串连接而不是path.join来加入路径
  5. 您不断轮询新数据而非等待其更改
  6. 您没有捕获可能引发异常的函数的异常
  7. 您不是在等待异步操作完成而您没有处理错误
  8. 您现在遇到的主要问题很可能是文件权限。好消息是,您不需要任何文件访问权限,因此无论如何使用文件都不是最佳选择。你需要的只是将颜色存储在一个变量中,如果你不需要它,它会在服务器重启之间持续存在 - 即使你这样做,我也会使用一个简单的数据库。

    例如:

    // 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);
    });
    

    这是我将使用的第一个更改 - 不依赖于文件系统,权限,竞争条件等。

    您的代码遇到的另一个问题是在请求处理程序中使用阻塞函数。除了事件循环的第一个刻度之外,你不应该使用任何阻塞函数(名称中带有“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

    享受。

答案 1 :(得分:0)

我认为,问题出在var dataStr = fs.readFileSync(dataPath).toString();。请按以下方式更改dataPath

 var dataPath = __dirname + '/data/color.tmp';

并确保该文件具有读取/写入权限。