javascript - 如何在 Node.js 上的控制器或外部文件上使用 Web 套接字?我无法访问 io 对象
问题描述
对不起英语:
我正在尝试制作一个 websocket 应用程序,但我无法访问控制器中的 websocket,我无法访问 io 控制器,我只能从 index.js 访问,但我无法从控制器:
我将我的应用程序划分为:
index.js:
//Importamos la app
const app = require('./app');
const socketIO = require('socket.io');
//Con el modulo 'dotenv' importamos las variables de entorno
//contenidas dentro del archivo '.env'
//Se recomienda correr este proyecto con permisos de administrador
require('dotenv').config();
//Importamos la conexion a la base de datos dentro de 'database.js'
require('./database/database');
//Esta funcion ejecuta el servidor
async function main(){
//Obtenemos el puerto
const PORT = app.get('port');
//Escuchamos el servidor en puerto y con '0.0.0.0' podemos acceder publicamente
server = await app.listen(PORT, '0.0.0.0');
const io=socketIO.listen(server);
//console.log('io index: ', io)
/*
io.on('connection', function(){
console.log('Socket Conectado');
io.emit('Prueba', 'Hola soy el
servidor'.toString());
});
*/
//Mostramos por consola
console.log('Servidor ejecutandose en el puerto: ', PORT);
};
main();
应用程序.js:
//Importamos 'express'
const express = require('express');
//Importamos 'morgan'
const morgan = require('morgan');
//Creamos una aplicacion
const app = express();
//Importamos 'cors'
const cors = require('cors');
//Importamos 'path' para poder manipular las rutas del sistema
const path = require('path');
//------------------------------------CONFIGURACIONES-----------------------------------
//Definimos el puerto
app.set('port', process.env.PORT || 3000);
//Archivos estaticos
app.use(express.static(path.join(__dirname, 'public')));//Configuramos la ubicacion de la carpeta 'public'
//--------------------------------------MIDDLEWARES-------------------------------------
//Configuramos 'morgan' en modo 'dev' para recibir mensajes de estado del servidor
app.use(morgan('dev'));
//Permitimos que el servidor entienda formato json
app.use(express.json());
//Permitimos la comunicacion con el frontend
app.use(cors());
//----------------------------------------RUTAS-----------------------------------------
//Usamos las rutas
//Rutas del servidor
app.use('/server', require('./routes/serverRoutes'));
//Rutas del dispositivo
app.use('/device', require('./routes/deviceRoutes'));
//--------------------------------------------------------------------------------------
//Exportamos el modulo
module.exports = app;
serverRoutes.js:
//Importamos el enrutador desde express
const {Router} = require('express');
//Importamos el 'middleware' 'verifyToken'
const verifyToken = require('../controllers/verifyToken');
//Importamos las funciones del controlador
const {createNewDevice, getDevicesStatus, modifyDeviceData} = require('../controllers/serverControllers');
//Ejecutamos la funcion y creamos un objeto 'router'
const router = Router();
//Creamos la ruta principal '/' para obtener el estado del 'device'
router.get('/', getDevicesStatus);
//Creamos una ruta por medio del metodo 'post' para crear un 'device'
router.post('/createDevice', createNewDevice);
//Creamos una ruta por medio del metodo 'put' para modificar o enviar al 'device'
router.put('/modifyData', verifyToken, modifyDeviceData);
//Exportamos el modulo
module.exports = router;
服务器控制器.js:
//Importamos el modelo de datos desde 'models/deviceModel.js'
const Device = require('../models/deviceModel');
const socketIO = require('socket.io');
const io = socketIO();
//Importamos el modulo de webtokens
//Un 'JSON web token' o 'JWT' es un arreglo de caracteres que sirve para
//contener las credenciales de acceso y cumple una funcion similar a un password
const jwt = require('jsonwebtoken');
//Importamos las configuraciones para jwt
const config = require('../../jwt_config');
//Almacenamos en un objeto todas las funciones del controlador
const deviceCtrl={};
//Con la notacion a continuacion relacionamos las funciones con el objeto 'notesCtrl'
//Funcion para crear un nuevo 'device'
deviceCtrl.createNewDevice= async(req, res) =>{
//Recibimos los datos en formato JSON
const{name}=req.body;
//Creamos un nuevo 'device'
const device = new Device({
name: name,
token: '0',
message: 'Dispositivo nuevo creado',
sensorStatus: '0',
rgbStatus: '0',
});
//Guardamos en la base de datos
await device.save();
//Creamos un nuevo 'token'
//Donde enviamos un dato , en este caso 'user._id' al cliente
//,usamos 'config.secret', para cifrarlo y con 'expiresIn' definimos el tiempo en
//segundos que durara el 'token' hasta su exporacion
const token = jwt.sign({id : device._id},
//Llamamos el valor 'secret' de 'jwt_config'
config.secret,
//En este caso sseria un dia
//{expiresIn: 60*60*24}
);
//Buscamos por 'id' y luego la actualizamos el dato 'token, en realidad
//NO es necesario guardarlo en la base de datos,
//esto es solo para poderlo reutilizar para pruebas
await Device.findByIdAndUpdate(device.id, {token});
//Cambiamos el parametro 'token' para poderlo ver
device.token=token;
console.log(device.message);
//Mostramos por consola
console.log(`New device: ${device}`);
//Enviamos la respuesta al cliente
res.json({
message: "New device created",
token: token
});
};
//Funcion para obtener el estado del dispositivo
deviceCtrl.getDevicesStatus = async (req, res) => {
console.log('io ctr: ', io)
socket.on('connection', function(){
console.log('Socket Conectado');
socket.emit('Prueba', 'Hola soy el servidor'.toString());
});
//Hacemos una consulta en todos los datos de la coleccion 'Device
const deviceStatus = await Device.find();
//Devolvemos el resultado de la consulta
res.json(deviceStatus);
};
//Funcion para modificar los datos dentro del dispositivo en este caso solo el LED RGB
deviceCtrl.modifyDeviceData = async(req,res) => {
//Como podemos acceder a 'req.userId' por medio 'verifyToken.js'
//lo usamos para hacer la consulta en la base de datos y modificar
const id = req.userId;
//Recibimos los datos en formato JSON
const{ message, rgbStatus}=req.body;
console.log('id: ', id)
//Hacemos la consulta en la base de datos
await Device.findByIdAndUpdate(id, {
message: message,
rgbStatus: rgbStatus
});
//Monstamos en consola
console.log(`Enviando al dispositivo: \n message: ${message}, rgbStatus: ${rgbStatus}`);
//Devolvemos al cliente
res.json({
message: message,
rgbStatus: rgbStatus
});
}
//Exportamos el modulo
module.exports = deviceCtrl;
谢谢您的帮助
解决方案
你的 index.js 说
const io = socketIO.listen(server)
io
您的任务是在需要的模块中获取在范围内调用的数据项 。实际上,一旦您async function main()
返回,它就会超出范围 - 消失。
节点有一个global
对象。因此,您可以将上面的行更改为
global.io = socketIO.listen(server)
然后global.io
在您需要在其他功能中使用它时提及。
专业提示如果你这样做,我建议你给它一个更具描述性的名字,比如
global.socketListener = socketIO.listen(server)
所以你和下一个处理你的代码的人会记得几年后发生的事情。
现在,看,全局变量通常被认为是有害的。所以要小心。
推荐阅读
- python - 带有 StringProperty() 的 Kivy 标记
- spring-boot - 如何将许多应用程序迁移到 Spring-Boot?策略和指南链接,而不是详细信息
- tcl - Tcl 反斜杠替换不像我想象的那样工作
- javascript - undefined 不是函数(评估'_this.props.navigation.navigate')
- node.js - 从客户端向服务器发送获取请求会导致 404 Next.js Express
- javascript - 创建和测试单个 Javascript 嵌套函数
- java - 如何检查给定的字符串转换为long是否是EpochMills?
- authentication - 有没有办法在应用层的 CoAP 中进行授权和身份验证?
- python - 如何拆分列表的键
- java - 更新 beans.xml 中的 Map 条目