最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Access SocketIO from another file - Stack Overflow

programmeradmin1浏览0评论

I'm trying to emit to all the sockets connected from a seperate file. However I cannot seem to figure it out.

Socket.js

var socketio = require('socket.io');
var users = require('./modules/users');

var io = socketio();
socket.io = io;

io.on('connection', function(socket){
  //Stuff
  console.log('Hello :)');
});

module.exports = socket;

Users.js

var socket = require('../socket');

function news(){
    socket.io.sockets.emit('news', {
        message: 'Woah! Thats new :)'
    })
}

setInterval(function(){
    news();
}, 5 * 1000);

However, socket in users.js seems to be empty and I can't seem to access to io object. How can I make it so I can emit to all users? Without parsing the io.sockets to the news function or moving my function to the socket file?

I'm trying to emit to all the sockets connected from a seperate file. However I cannot seem to figure it out.

Socket.js

var socketio = require('socket.io');
var users = require('./modules/users');

var io = socketio();
socket.io = io;

io.on('connection', function(socket){
  //Stuff
  console.log('Hello :)');
});

module.exports = socket;

Users.js

var socket = require('../socket');

function news(){
    socket.io.sockets.emit('news', {
        message: 'Woah! Thats new :)'
    })
}

setInterval(function(){
    news();
}, 5 * 1000);

However, socket in users.js seems to be empty and I can't seem to access to io object. How can I make it so I can emit to all users? Without parsing the io.sockets to the news function or moving my function to the socket file?

Share Improve this question asked Feb 22, 2019 at 1:48 BordaBorda 1392 silver badges11 bronze badges 1
  • @JackBashford I'm pretty sure it doesn't matter for whether you add the .js or not, I like doing it like this as it looks clean. – Borda Commented Feb 22, 2019 at 1:49
Add a comment  | 

4 Answers 4

Reset to default 14

You can define io object with let as global variable in utils and io functions there. You can call these functions from any file. For example:

// app.js

const { socketConnection } = require('./utils/socket-io');
const http = require('http');
const express = require('express');

const app = express();
const server = http.createServer(app);
socketConnection(server);

// utils/socket-io

let io;
exports.socketConnection = (server) => {
  io = require('socket.io')(server);
  io.on('connection', (socket) => {
    console.info(`Client connected [id=${socket.id}]`);
    socket.join(socket.request._query.id);
    socket.on('disconnect', () => {
      console.info(`Client disconnected [id=${socket.id}]`);
    });
  });
};

exports.sendMessage = (roomId, key, message) => io.to(roomId).emit(key, message);

exports.getRooms = () => io.sockets.adapter.rooms;

// any file

const { sendMessage } = require('../utils/socket-io');

const foo = async () => {
  const roomId = '12345';
  const key = 'new-order';
  const message = 'new order assigned';
  
  sendMessage(roomId, key, message);
};

Just create a socket service object, the service object only published some helper functions.

Example for your case:

// Socket.js
var socketio = require('socket.io');
var users = require('./modules/users');

var io = socketio();
socket.io = io;

io.on('connection', function (socket) {
  //Stuff
  console.log('Hello :)');
});

var toAll = function (eventName, data) {
  io.sockets.emit(event, data);
}

module.exports = {
  toAll: toAll // publish `toAll` function to call every where
};


// Users.js
var socketService = require('../socket');

function news() {
  socketService.toAll('news', {
    message: 'Woah! Thats new :)'
  });
}

setInterval(function () {
  news();
}, 5 * 1000);

Based on the answer from Furkan Uyar, I created a Typescript service

// utils/socket-io.service.ts

import {Server, ServerOptions} from "socket.io";
import {Server as HttpServer} from "http";

export class SocketIOService {
  private static _instance: SocketIOService | undefined;
  private static server: Server | undefined;

  private constructor() {
    // Private constructor ensures singleton instance
  }

  static instance(): SocketIOService {
    if (!this._instance) {
      return new SocketIOService();
    }

    return this._instance;
  }

  initialize(httpServer: HttpServer, opts?: Partial<ServerOptions>) {
    SocketIOService.server = new Server(httpServer, opts);

    return SocketIOService.server;
  }

  ready() {
    return SocketIOService.server !== null;
  }

  getServer(): Server {
    if (!SocketIOService.server) {
      throw new Error('IO server requested before initialization');
    }

    return SocketIOService.server;
  }

  sendMessage(roomId: string | string[], key: string, message: string) {
    this.getServer().to(roomId).emit(key, message)
  }

  emitAll(key: string, message: string) {
    this.getServer().emit(key, message)
  }

  getRooms() {
    return this.getServer().sockets.adapter.rooms;
  }
}

The service must be initialized before use:

// app.ts
import express from "express";
import log from "./logger";
import cors from "cors";
import {createServer} from "http";
import {SocketIOService} from "./utils/socket-io.service";


const app = express();
const httpServer = createServer(app);

SocketIOService.instance().initialize(httpServer, {
  cors: {
    origin: ['http://localhost:4200']
  }
});

const io = SocketIOService.instance().getServer();

io.on('connection', (socket) => {
  log.info('a user connected');

  socket.on('disconnect', () => {
    log.info('user disconnected');
  });

  socket.on('my message', (msg) => {
    console.log('message: ' + msg);

    io.emit('my broadcast', `server: ${msg}`);
  });

  socket.on('room_update', (msg) => {
    console.log('message: ' + msg);
  })
});

// ...

And then to call the service from another file (e.g. a HTTP Handler)

import {SocketIOService} from "../utils/socket-io.service";
import log from "../logger";

function notifyUpdatedRoom(roomId: string) {
  log.info(`Notifying on updated room: ${roomId}`);

  if (roomId && SocketIOService.instance().ready()) {
    SocketIOService.instance().emitAll('room_update', roomId);
  }
}

I managed to solve this by changing the position from the module.exports. I immediately put it after I initialized the socket variable, as it's the only thing I'm exporting it works.

发布评论

评论列表(0)

  1. 暂无评论