node.js - 当活动套接字只有一个时,NodeJs 无法监听 socket.io 私有通道
问题描述
我正在广播nodejs之间的连接,并且颤动......我正在向私人频道发射,并收听同一个频道。
我在 server.js 中定义 socket.io 配置,然后,我使用它的一个实例@authcontroller.js。
我遇到的问题是,当我尝试从 auth.controller 收听私人频道时,只有当活动套接字超过一个套接字时,我才会收到响应。但是,即使只有一个套接字,我也会从 server.js 立即收到响应。
下面是代码:
服务器.js
//general dependencies
const port = process.env.PORT || 3000;
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
const fileUpload = require('express-fileupload');
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}))
const api = require('../api/AuthController')
var server = http.listen(3000, () => {
console.log('server is running on port', server.address().port);
});
//routes
const routes = require('../api/routes');
routes(app,io);
//socket config
global.io = io; //added
io.on('connection', function(socket){
socket.on('privateChannelID', function (message) {
console.log('message received from server.js')
});
});
AuthController.js:
global.io.on('connection', function (socket) {
socket.on('privateChannelID', function (message) {
console.log('message received from authcontoller')
});
});
任何想法,我错过了什么?
提前致谢
更新
前端代码:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:adhara_socket_io/adhara_socket_io.dart';
import 'package:geocoder/geocoder.dart';
const String URI = "http://10.0.2.2:3000/";
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
_MyHomePageState();
List<String> toPrint = ["trying to connect"];
SocketIOManager manager;
Map<String, SocketIO> sockets = {};
Map<String, bool> _isProbablyConnected = {};
bool newtripRequest = false;
var pickupController;
var dropoffController;
SocketIO socketController;
var driver = 'driver';
String socketIdentifier;
@override
void initState() {
super.initState();
manager = SocketIOManager();
initSocket("default");
}
@override
void dispose() {
super.dispose();
}
initSocket(String identifier) async {
setState(() => _isProbablyConnected[identifier] = true);
SocketIO socket = await manager.createInstance(SocketOptions(
//Socket IO server URI
URI,
nameSpace: (identifier == "namespaced") ? "/adhara" : "/",
//Query params - can be used for authentication
query: {
"auth": "--SOME AUTH STRING---",
"info": "new connection from adhara-socketio",
"timestamp": DateTime.now().toString()
},
//Enable or disable platform channel logging
enableLogging: false,
transports: [
Transports.WEB_SOCKET /*, Transports.POLLING*/
] //Enable required transport
));
setState(() {
socketIdentifier = identifier;
});
socket.onConnect((data) {
pprint("connected...");
pprint(data);
sendMessage('news', 'yes', socketIdentifier);
});
socket.onConnectError(pprint);
socket.onConnectTimeout(pprint);
socket.onError(pprint);
socket.onDisconnect(pprint);
socket.on("news", (data) => newTripRquest(data));
socket.connect();
sockets[identifier] = socket;
}
bool isProbablyConnected(String identifier) {
return _isProbablyConnected[identifier] ?? false;
}
disconnect(String identifier) async {
await manager.clearInstance(sockets[identifier]);
setState(() => _isProbablyConnected[identifier] = false);
}
sendMessage(privateChannel, messageBody, identifier) {
//pprint("sending message from '$identifier'...");
sockets[identifier].emit(driverChannel, [
{'response' : messageBody}]);
//pprint("Message emitted from '$identifier'...");
}
pprint(data) {
setState(() {
if (data is Map) {
data = json.encode(data);
}
print(data);
toPrint.add(data);
});
}
更新:
AuthConroller.js
'use strict'
const jwt = require("jsonwebtoken");
const bcrypt = require("bcryptjs");
var authController = {
findNearestDriver: function (req, res) {
var query = Driver.find({
'geo': {
$near: [
req.body.lat,
req.body.lng
],
// $maxDistance: distance
}
});
query.exec(async function (err, driver) {
if (err) {
console.log(err);
throw err;
}
if (!driver) {
res.json({});
} else {
for (let i = 0; i < driver.length; i++) {
global.io.emit(`news${driver[i]._id}`, {
pickupLat: req.body.lat, pickupLng: req.body.lng, dropOffLat:
req.body.dropLat, dropOffLng: req.body.dropLng });
global.io.on('connection', function (socket) {
socket.on(`news${driver[i]._id}`, function (message) {
if (message.message === 'Accept') {
resultRecieved = true
console.log('message received')
}
});
});
}
res.json(driver);
}
});
}
}
module.exports = authController;
解决方案
在 里面authController.js
,你有一个:
global.io.on('connection', ...)
嵌入在其他一些功能findNearestDriver()
中。findNearestDriver()
因此,该连接事件处理程序在调用并执行函数之后以及其中的查询完成之前不会处于活动状态。这意味着您将错过connection
调用该函数之前发生的任何事件。
它也在一个for
循环中,这几乎不是您想要的,因为它只会创建相同但重复的事件处理程序。
像这样的事件处理程序global.io.on('connection', ...)
通常应该靠近模块的顶层并在模块初始化时进行初始化,而不是在可以多次运行的地方。
请注意,您也在加载authController.js
之前global.io
有一个值。这意味着您不能只将 移动global.io.on('connection', ...)
到模块的顶层,除非您也将require('authController.js')
AFTERglobal.io
设置为 AFTER 。
但是,我认为您需要对这部分的authController.js
工作方式进行一些重新设计,因为connection
事件处理程序需要位于模块的顶层,而不是深埋在for
函数内部的循环中。
这很好地说明了在涉及异步操作时使用全局变量进行通信的问题之一。它会产生令人沮丧的时间或加载顺序问题。IMO,最好io
在模块构造函数中显式传递给这个模块并从那里使用它,而不是从全局使用它。这将使您不太可能以io
在初始化之前尝试使用的方式对其进行编码。
推荐阅读
- reactjs - 从 React 组件创建 Html,包括样式
- vba - Checkbox Yes/No Change on Dropbox Change
- python-3.x - ValueError:RGBA 参数无效
- javascript - 当前日期到 React App 中的环境变量中
- git - git fsck:duplicateEntries:包含重复的文件条目 - 无法推送到 gitlab
- python-3.x - 如何从数据框的列中消除 3 个字母词或 4 个字母词
- gradle - Windows 上的 Gradle 执行命令
- google-chrome - W3C Pay(Bobpay 示例 chrome 扩展) - MAC OS - 无法重定向到 chrome 扩展。在 Windows 上工作
- java - 识别 java 中 gerDeclaredMethod 所需参数的类类型
- python - 对 pandas 数据框执行复杂搜索的最快方法