【问题标题】:How to emit socket.io event from express controller on typescript?如何从打字稿上的快速控制器发出 socket.io 事件?
【发布时间】:2022-01-23 10:26:17
【问题描述】:

我正在学习 socket.io 和 typescript。我目前正在构建一个应用程序,我想在数据库更改时向客户端发出事件。对于后端,我使用的是 Express、typescript 和 nodeJS

我查看了很多帖子,但我不明白如何访问我的 io 实例以便能够从我的控制器函数中发出我的事件。此外,大多数示例都在更令人困惑的 javascript 上。

目前在我的 app.ts 中,我有以下配置。如何在我的控制器函数中移动我的 addOnlineHandler、logOutHandler 和 sendNotificationHandler 以便能够直接从控制器的 createOrder 函数发出数据库更改事件?

我尝试在控制器中导入所有 orderHandler 函数,但它不起作用。我无法访问 io 实例来发出事件。

app.ts

import  express  from "express";
import dotenv from "dotenv";
import userRoute from './routes/user'
import mongoose from "mongoose";
import { createServer } from "http";
import { Server,Socket } from "socket.io";
import {addOnlineShopHandler,logOutHandler, sendNotificationHandler} from "./socket/orderHandler";


dotenv.config();
const app = express();

const httpServer = createServer(app);

const io = new Server(httpServer, {
    cors:{
        origin:"*"
    }
});

const onConnection = (socket:Socket) => {
    addOnlineShopHandler(socket)
    logOutHandler(socket)
    sendNotificationHandler(socket)
    
  }

io.on("connection",onConnection)


httpServer.listen(process.env.PORT, () => {
    console.log('Backend server is running')
});

const connectToDatabase = async (dbConnectionString:string) => {
    await mongoose.connect(dbConnectionString)
    console.log('Connection to DB sucess')
}

connectToDatabase(`${process.env.MONGO_URI}`).catch(err => console.log(err))

app.use('/api/users',userRoute)

我需要在创建订单时发出事件的控制器文件。

orderController.ts

import { RequestHandler } from "express";


export const createOrder:RequestHandler = async (req, res) => {
    // I want to use socket.io in this function 
    // emit event when order created 


}

我的 orderHandler 文件。

orderHandler.ts

import { Server,Socket } from "socket.io";

interface IOnlineShop {
    shopId:string, 
    socketId:string
}

let onlineShop:IOnlineShop[] = []

export const addOnlineShopHandler = (socket:Socket) => {
    console.log('someone is in')
    
    const addNewShop = (shopId:string, socketId:string) => {
        !onlineShop.some((currentShop) => currentShop.shopId === shopId) && onlineShop.push({shopId,socketId})
    }
    const newShopConnected = (shopId:string) => {
        addNewShop(shopId,socket.id)
    }

    socket.on('newShopConnected',newShopConnected)

}

export const logOutHandler = (socket:Socket) => {

    const removeShop = (socketId:string) => {
        onlineShop = onlineShop.filter((currentShop)=>{currentShop.socketId !== socketId})
        console.log('someone is out')
    }
    socket.on('disconnect',removeShop)
    
}


export const sendNotificationHandler = (socket:Socket) =>{
    const getUser = (shopId:string) =>{
        return onlineShop.find((currentShop) => currentShop.shopId === shopId)}
    const sendNotification = (data:any) =>{
        const receiver = getUser('randomshopId')
        console.log(receiver)
    }

    socket.on("sendNotif",sendNotification)
}


我查看了这些帖子,但仍然无法绕过解决方案,也许使用打字稿让我感到困惑。工作流程的任何帮助或解释将不胜感激。 how to use socket.io in controller fileUse socket.io in controllers Socket.IO + Express framework | Emit/Fire From Express Controller & Router

谢谢,

【问题讨论】:

    标签: node.js typescript express socket.io


    【解决方案1】:

    您可以将io 附加到应用对象:

    app.set('io', io);
    

    然后您可以使用req.app.get('io')从控制器中访问它

    【讨论】:

    • 感谢您的回答,它似乎正在发出!但我无法从控制器内的客户端获取事件。你现在有没有想到为什么 io.sockets.on 没有从客户端获取数据?
    • 要在控制器中设置监听器(我不知道这是否是好的做法),您需要将socket 对象附加到onConnection 函数中的应用程序。然后你可以在控制器内部访问这个套接字对象并在其上设置一个监听器。
    • 但是我认为你永远不应该这样做,因为它会在每次调用控制器时添加一个监听器。也许 socketio rooms 可以帮助你。
    猜你喜欢
    • 2017-02-22
    • 2022-12-11
    • 2019-05-31
    • 2014-07-07
    • 2021-01-08
    • 2020-10-25
    • 2014-04-30
    • 2015-07-19
    • 1970-01-01
    相关资源
    最近更新 更多