40692


### 前提・実現したいこと

socket.ioとNode.jsを用いて、あるディレクトリにファイルが追加された時  
その内容をイベントとしてクライアントに送るシステムを構築しています。

### 発生している問題・エラーメッセージ

下記該当のソースコードにあるようなコードを記述しているのですが  
クライアントの接続を切断してもsocket.idが廃棄されず、今まで接続していたクライアント全てに飛ばしているような  
挙動を示します。  
例）3回ブラウザを更新すると、4回分のイベントが発行されているような挙動  
どのように修正すれば、切断時にsocket.idが廃棄され、現在接続しているクライアントのみに  
イベントを飛ばすようになるのでしょうか。

### 該当のソースコード

[code]

    JavaScript
    //lib
    var express = require('express')
    var app = express();
    var chokidar = require('chokidar');
    var fs = require('fs');
    var server = require ('http').Server(app);
    var io = require('socket.io')(server);
    var filepath = require('path');
    
    let clients = {};
    
    var watcher = chikidar.watch('./***/',{
        ignored:/[\/\\]\./,
        persistent:true,
        alwaysStat:true,
        }
    });
    
    app.get('/',req,res)=>{
       res.SendFile(__dirname + './***.html');
    });
        
    io.on('connection',(socket)=>{
        clients[socket.id]= socket;
        console.log(socket.id+'connected')
        watcher.on('add',function(path){
    ///fsでファイルを読む処理をしています。
        io.json.to(socket.id).emit(～～～);
    });// watcher
    socket.on('命令1',function(data){
        console.log(socket.id)
        console.log('命令1が来た')
    ///fsでファイルを消しています。
    });
    socket.on('disconnect',(reason)=>{
         delete clients;
         console.log(socket.id+'disconnected')
    });
    });
    
[/code]

### 出力

例えば3回更新した時はこのように出力されます。

[code]

        [Time] (socket.id1) connected
        [Time] (socket.id1) disconnected
        [Time] (socket.id2) connected
        [Time] (socket.id2) disconnected      
        [Time] (socket.id3) connected
    
[/code]

この時にemitさせるとこのように出力されます

[code]

        [Time] (socket.id1)
        [Time] 命令1が来た
        [Time] (socket.id2)
        [Time] 命令1が来た
        [Time] (socket.id3)
        [Time] 命令1が来た
    
[/code]

### 追記

上記コードを以下の様に変更したところ

[code]

    io.on('connection',(socket)=>{
        var info = io.sockets.client();
        var count = Oblect.keys(info.connected).length
        console.log(info); //出力1
        console.log(count); //出力2
        clients[socket.id]= socket;
        watcher.on('add',function(path){
        ・・・
    
[/code]

出力1,2どちらも接続されている分しか出ませんでした。  
例）2ブラウザで接続した際は、出力は2と出力  
しかし、イベントを発火させた際、命令1が来たといった出力は変わらず今まで接続されていた  
分出力されてしまいます。

### マルチポスト

[teratail](https://teratail.com/questions/102422#)


CC BY-SA 3.0
2017-12-10T12:21:39.323
40169
2018-01-03T14:19:38.693
2020-06-17T08:14:45.997
-1
13593
question
javascript html node.js socket.io
Socket.IOでクライアントを切断しても、今まで接続されていたクライアント分イベントが飛ぶ


接続があるたびに `watcher.on('add',...);` でハンドラを登録して、削除していないので、  
当然のように思います。かといって、削除をする手段は用意されていないようです。

そこで、`watcher.on('add', ...);` は接続時のハンドラ内で行うのではなく、  
外で一度だけ実行すべきだと思います。

[code]

    watcher.on('add', function(path) {
        for (var id in clients) {
            io.json.to(id).emit(～～～);
        }
    });
    
    io.on('connection', (socket) => {
        // ここでは watcher.on('add, ...); しない。
    
        // ...
    
        socket.on('disconnect',(reason)=>{
             delete clients[socket.id];          // ←ここも修正
             console.log(socket.id+'disconnected')
        });
    });
    
[/code]

つながっている socket は `io` から得られるのでは、と思いますが、  
socket.io は私には門外漢でよくわからないので、`clients` を使いました。


CC BY-SA 3.0
2018-01-03T14:19:38.693
40692
2018-01-03T14:19:38.693
5288
40169
answer