Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript readFile未在while循环中运行_Javascript_Node.js_Sockets_Express - Fatal编程技术网

Javascript readFile未在while循环中运行

Javascript readFile未在while循环中运行,javascript,node.js,sockets,express,Javascript,Node.js,Sockets,Express,每次使用Express更新文本文件时,我都试图通过套接字连接发送文本文件的内容: console.log('Server running!'); var express = require('express'); var app = express(); var server = app.listen(3000); var fs = require("fs"); var x = 0; app.use(express.static('public')); var socket = requi

每次使用Express更新文本文件时,我都试图通过套接字连接发送文本文件的内容:

console.log('Server running!');

var express = require('express');
var app = express();
var server = app.listen(3000);
var fs = require("fs");
var x = 0;

app.use(express.static('public'));

var socket = require('socket.io');
var io = socket(server);

io.sockets.on('connection', newConnection);

function newConnection(socket) {
  console.log("New connection: " + socket.id);
  while (true) {
    fs.readFile('song.txt', function(err, data) {
      if (err) throw err;
      console.log(data);
      if (data != x) {
        var songdata = data;
        console.log(songdata);
        io.sockets.emit('update', songdata);
        x = data;
      } else {
        console.log("Song is not different:)");
      }
    })
  }
}
没有while循环,一切正常,我在单独的客户机中接收内容。但是,现在什么都没有发生,没有控制台日志数据。这表明readFile突然不再运行,为什么


谢谢:

首先,一些基础知识。js将Javascript作为单线程运行,因此这是一个单线程服务器。它一次只能用Javascript做一件事。但是,如果你仔细编程,它可以很好地扩展并做很多事情

其次,在服务器端Javascript中,您几乎不想这样做。这将永远运行,永远不会让其他任何东西在您的服务器上运行。没有别的了

第三,每次新客户端连接时,您都试图创建无限循环的新版本。即使没有无限循环,这也不是一个正确的设计。您只需要检查文件的一个代码实例,而不是N

现在,如果您真正想做的是轮询song.txt中的更改,并在更改时通知客户端,那么您需要在文件检查之间选择一个合理的时间差,并使用计时器。这将每隔一段时间检查一次该文件,并让您的服务器一直正常运行

下面是一个使用setInterval进行轮询的简单版本:

如果您的songData是二进制的,那么您必须更改向客户端发送数据的方式,以及将数据与以前的数据进行比较的方式,以便发送和接收二进制数据,而不是字符串数据,从而比较缓冲区,而不是字符串

以下是有关使用socket.io发送二进制数据的一些参考资料:

检测文件更改的一种更有效的方法是使用fs.watch,它会通知您文件的更改,尽管您必须在运行的任何平台上对其进行彻底测试,以确保其按您想要的方式工作。该功能有许多优点,但并非在所有平台上都能完全相同地工作,因此您必须在您的平台上对其进行彻底测试,以确定是否可以将其用于您想要的用途

console.log('Server code started!');

const express = require('express');
const app = express();
const server = app.listen(3000);
const fs = require("fs");
let lastSongData = 0;

app.use(express.static('public'));

const io = require('socket.io')(server);

// get initial songData for future use
// there will not be any connected clients yet so we don't need to broadcast it
try {
    lastSongData = fs.readFileSync('song.txt');
} catch(e) {
    console.log(e, "\nDidn't find song.txt on server initialization");
}

// ask node.js to tell us when song.txt is modified
fs.watch('song.txt', (eventType, filename) => {
    // check the file for all eventTypes
    fs.readFile('song.txt', (err, songData) => {
        if (!err && songData !== lastSongData) {
            // notify all connect clients
            console.log("found changed songData");
            lastSongData = songData;
            io.emit('update', songData);
        }
    });
});

io.sockets.on('connection', socket => {
  console.log("New connection: " + socket.id);
});
您的原始代码不清楚您是否需要将songData发送到每个新连接,无论它最近是否发生了更改

如果是这样,您只需将连接事件处理程序更改为:

io.sockets.on('connection', socket => {
  console.log("New connection: " + socket.id);
  // send most recent songData to each newly connected client
  if (lastSongData) {
      socket.emit('update', lastSongData);
  }
});

连续读取文件以检测更改不是一个好主意。相反,您应该使用在文件更改时通知您。当一个新的套接字只连接该套接字时,该套接字应该向它们广播内容,将其发送到每个客户端是多余的

io.sockets.on('connection', newConnection);

var filename = 'song.txt';

function update(socket) {
    fs.readFile(filename, function (err, data) {
        if (err) throw err;
        socket.emit('update', data);
    });
}

function newConnection(socket) {
    console.log("New connection: " + socket.id);
    update(socket); // Read and send to just this socket
}

fs.watch(filename, function () {
    console.log("File changed");
    update(io.sockets); // Read and send to all sockets.
});

readFile是异步的。异步回调在代码返回到主事件循环之前不会运行,但您有一个无限while循环,因此它永远不会返回。请重新设计代码以异步工作,或者使用readFileSync。另一方面,与在循环中读取文件相比,有更有效的方法监视对文件的更改,这样做的话,阅读量会比需要的多。Node 10现在有了fs.watch:谢谢大家:我已经切换到readFileSync,并且在没有循环的情况下工作了。当我再次放入循环时,io.sockets.emit行不再运行。那也是异步的吗?谢谢,伙计,这太棒了,正是我需要的。非常感谢你@jbblackett-如果您的songData是二进制的,那么您必须调整它,以便通过socket.io发送二进制数据,将二进制数据与以前的songData进行比较,并在客户端读取二进制数据。如果是字符串,这应该是好的。
io.sockets.on('connection', newConnection);

var filename = 'song.txt';

function update(socket) {
    fs.readFile(filename, function (err, data) {
        if (err) throw err;
        socket.emit('update', data);
    });
}

function newConnection(socket) {
    console.log("New connection: " + socket.id);
    update(socket); // Read and send to just this socket
}

fs.watch(filename, function () {
    console.log("File changed");
    update(io.sockets); // Read and send to all sockets.
});