Javascript 执行快速(v4)路由时,Socket.io double发出

Javascript 执行快速(v4)路由时,Socket.io double发出,javascript,node.js,socket.io,Javascript,Node.js,Socket.io,我在执行express(v4)路由时遇到双重发射问题 例如,让我们运行下面的代码。请求(管道)和mkdir将立即启动(竞争条件),并且会出现关于文件夹不存在的错误(在请求启动和开始管道数据之前,mkdir无法足够快地创建它)。此错误的原因用户被重定向到第X页,在那里他需要重新填写表单。现在(通过表单重新填充重定向后)一切正常(因为文件夹在数据到达时确实存在,因为它是在之前创建的-因为异步操作必须完成?-路由在“后面”执行代码,即使用户已经重定向),但发射会执行两次-一次用于旧数据,一次用于新数据

我在执行express(v4)路由时遇到双重发射问题

例如,让我们运行下面的代码。请求(管道)和mkdir将立即启动(竞争条件),并且会出现关于文件夹不存在的错误(在请求启动和开始管道数据之前,mkdir无法足够快地创建它)。此错误的原因用户被重定向到第X页,在那里他需要重新填写表单。现在(通过表单重新填充重定向后)一切正常(因为文件夹在数据到达时确实存在,因为它是在之前创建的-因为异步操作必须完成?-路由在“后面”执行代码,即使用户已经重定向),但发射会执行两次-一次用于旧数据,一次用于新数据(复制HTML页面结构的一部分)

x.js文件中的路由:

router.post('/Y', function(req, res) {
    request(opt, function(err, resp, body) {
        if (resp.statusCode === 200) {
            res.render('Y'); // so the emits can target something (they build html structure on page 'Y' with proper data)

            function socCon()
            {
                var room = '';
                return new Promise(function(resolve, reject)
                {
                    req.io.on('connection', function(socket)
                    {
                        room = 'room-' + socket.id;
                        socket.join(room);

                        if (socket.join(room)) {
                            resolve(room);
                        }
                        else {
                            reject(console.log('error'));
                        }
                    });
                });
            }
            socCon().then(data).catch(function(error)
            {
                console.log(error);
            });

            function data(room) {

                var myFolder = 'myFolder/';

                fs.mkdir(myFolder, {recursive : true}, function(err) {
                    if (err) {console.log(err);}
                });

                var file = fs.createWriteStream(myFolder + 'data.html', 'utf8');

                sio.emit('msg', {emit : emit}); // socket.io emits - with use of express route POST on page 'X'

            });
        }
        else {
            res.render('X', {ERRORS : ERRORS});
            res.end();
        }
    }).on('response', function(response) {
    }).pipe(file).on('error', function(err) {
        res.render('X', {ERRORS : ERRORS}); // we inform the user that he put wrong data in input field or that there is internal server error (whatever)
        res.end();
        // so we end 'Y' page connection here (but socket.io somehow collect all the data, emit it later on - when same route is hit again) and socket.sendBuffer does not work)
    });
)};
有什么方法可以阻止旧的emit吗?我尝试了
socket.sendBuffer=[];
(@jfreind00 suggestion at-)但没有效果。理想的方法是…在有重定向时停止整个请求。但是你不能停止异步代码的执行(或者我不知道如何)

客户端第Y页:

<!DOCTYPE html>
<html>
<head>
    <title>TITLE</title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
    socket.on('connect', function() {
        socket.sendBuffer = []; // does not work...
    });
    socket.on('msg', function(msg) {
        // some HTML mutation here
    });
</script>
</body>
</html>
这行代码:

req.io.on('connection', function(socket) {...});
每次运行此路由时,只需添加一个新的重复事件处理程序。因此,在运行两次路由后,
连接
事件将有两个事件处理程序。在运行三次路由后,
连接
事件将有三个事件处理程序,依此类推。它们只是累积,永远不会消失

因此,这就解释了重复处理的原因。您有重复的事件处理程序,因此同一
连接
事件会被多次处理


我真的无法提出修复建议,因为我没有遵循您试图实现的目标,而试图捕获下一个
连接
事件并假设该事件属于特定页面的整个方案是有缺陷的(充满竞争条件问题)-更不用说它添加了一组永无止境的重复事件处理程序。对于任何路由处理程序之外的
连接
事件,您将需要一个侦听器,然后使用该传入事件执行任何您想执行的操作。

我实际上不明白您在这里询问的是哪一个特定问题。请概述exact发生的步骤和您想要发生的事情。是否从浏览器转到
http://somedomain.com/Y
,那么到底发生了什么?由于您无法
.emit(),所以不清楚您要将
.emit()发送给谁
到浏览器正在加载的页面。另外,
请求()
和“.pipe()”背后的原因是什么?您试图对您创建的文件做什么?是一个带有输入字段的起始域。如果用户填充了该域,则路径将引导他到。当他浏览页面时,路径将在Y处由请求生成(在路由POST Y中)发送并更新页面。但有时(例如,当文件夹未按时创建时-用户被重定向到第X页,需要再次填写输入)发送两次。请求检查并下载数据,我希望存储文件(包含请求的数据),以便稍后我可以将其与新的进行比较。那么,为什么不先修复
mkdir()呢
您显然已经知道的问题?谁会获得双发射?我还不了解这一部分。是的,它很容易通过asyns/await解决,我只想说明问题-但发射不应加倍。用户获得双发射(旧数据,可能是因为异步代码在“后面”运行)+他刚才传递的新数据)。例如,当服务器给我们错误时,也会发生这种情况-当再次检查相同的数据时,用户确实会加倍/加倍等。发出。Socket.io不知何故知道此id已连接到此用户(代理?)即使每个新的socket io连接都使用新ID,它也会设法将旧用户ID与新用户ID连接(?)并发送数据。我想使用socket.io与用户连接并仅为他发送数据-没有连接和自定义房间,我只能针对所有用户。移动到新页面时,会导致socket.io断开连接(重定向)我确实尝试为此使用路由(在移动到Y时从第X页保存数据)。我在index.js上确实有连接-但这不是我希望的工作方式-用户在移动到“/Y”时断开连接,需要检查/下载的数据丢失。在页面之间移动时,我无法保持socket.io连接。我仍然不太明白socket.io在运行两次此路由时如何向同一用户发送目标(因为每次都有不同的连接ID,当scoket.io连接丢失时,用户会自动从文件室解除绑定-具有无效ID的旧连接如何工作?)。当我从“/Y”页移动到“/X”页(没有错误时)并再次填写表单时-工作正常(相同的路径)。当我刷新“/Y”页时,工作正常(再次使用相同的路由)。只有当出现错误(用户自动重定向到“/X”页)并再次使用表单(路由)时,才会发出重复。为什么socket.sendBuffer=[];不工作?抱歉,这里的速度太慢,这对我来说是全新的。谢谢您的帮助。@b4rtekb-您知道每次运行
req.io.on时都是如何操作的吗('connection',函数(套接字){…});
,它为
连接
事件添加了一个新的全局socket.io处理程序,并且由于您从未删除这些事件处理程序,因此在点击路由5次后,它们会累积起来,然后您就安装了该事件处理程序的5个副本?因此,每次
连接
事件发生之后,您都会运行事件处理程序代码5es?你了解这种结构的基本缺陷吗?这解释了你看到的重复消息。@b4rtekb-你从来没有真正从第一原理描述过你在这里要做什么,但在我看来,你需要一种完全不同的方法来解决这个问题,因为你有多个缺陷
req.io.on('connection', function(socket) {...});