Я использую Node.js для создания микросервиса для загрузки мультимедиа. Эта служба работает, беря двоичные данные загрузки в буфер, а затем используя пакет S3 npm для загрузки в ведро S3. Я пытаюсь использовать eventEmitter, присутствующий в этом пакете, который показывает объем данных, загружаемых на S3, и посылает их обратно клиенту, который выполняет загрузку (чтобы они могли видеть прогресс загрузки). Я использую socket.io для отправки данных прогресса клиенту.Socket.io не может передавать данные в уникальную комнату клиента
Проблема, с которой я столкнулась, заключается в том, что событие .emit в socket.io отправит данные о ходе загрузки для всех подключенных клиентов, а не только для клиента, который инициировал загрузку. Как я понимаю, сокет соединяется с комнатой по умолчанию на «соединении», которая зеркально отражается на «id» на стороне клиента. Согласно официальным документам, использование socket.to (id) .emit() должно отправлять данные только для этого клиента, но это не работает для меня.
ОБНОВЛЕНО Пример кода:
server.js:
var http = require('http'),
users = require('./data'),
app = require('./app')(users);
var server = http.createServer(app);
server.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
var io = require('./socket.js').listen(server);
socket.js:
var socketio = require('socket.io');
var socketConnection = exports = module.exports = {};
socketConnection.listen = function listen(app) {
io = socketio.listen(app);
exports.sockets = io.sockets;
io.sockets.on('connection', function (socket) {
socket.join(socket.id);
socket.on('disconnect', function(){
console.log("device "+socket.id+" disconnected");
});
socketConnection.upload = function upload (data) {
socket.to(socket.id).emit('progress', {progress:(data.progressAmount/data.progressTotal)*100});
};
});
return io;
};
s3upload.js:
var config = require('../config/aws.json');
var s3 = require('s3');
var path = require('path');
var fs = require('fs');
var Busboy = require('busboy');
var inspect = require('util').inspect;
var io = require('../socket.js');
...
var S3Upload = exports = module.exports = {};
....
S3Upload.upload = function upload(params) {
// start uploading to uploader
var uploader = client.uploadFile(params);
uploader.on('error', function(err) {
console.error("There was a problem uploading the file to bucket, either the params are incorrect or there is an issue with the connection: ", err.stack);
res.json({responseHTML: "<span>There was a problem uploading the file to bucket, either the params are incorrect or there is an issue with the connection. Please refresh and try again.</span>"});
throw new Error(err);
}),
uploader.on('progress', function() {
io.upload(uploader);
}),
uploader.on('end', function(){
S3Upload.deleteFile(params.localFile);
});
};
При использовании DEBUG = * узел myapp.js, я вижу socket.io-pa rser принимая в этой информации, но она не излучающие его клиенту:
socket.io-parser encoding packet {"type":2,"data":["progress",{"progress":95.79422221709825}],"nsp":"/"} +0ms
socket.io-parser encoded {"type":2,"data":["progress",{"progress":95.79422221709825}],"nsp":"/"} as 2["progress",{"progress":95.79422221709825}] +0ms
Однако, если я удалить .to часть этого кода, он посылает данные клиенту (хотя всем клиентам, который не будет помогать вообще):
io.sockets.on('connection', function(socket) {
socket.join(socket.id);
socket.emit('progress', {progress: (data.progressAmount/data.progressTotal)*100});
});
DEBUG = * узловые myapp.js:
socket.io:client writing packet {"type":2,"data":["progress",{"progress":99.93823786632886}],"nsp":"/"} +1ms
socket.io-parser encoding packet {"type":2,"data":["progress",{"progress":99.93823786632886}],"nsp":"/"} +1ms
socket.io-parser encoded {"type":2,"data":["progress",{"progress":99.93823786632886}],"nsp":"/"} as 2["progress",{"progress":99.93823786632886}] +0ms
engine:socket sending packet "message" (2["progress",{"progress":99.93823786632886}]) +0ms
engine:socket flushing buffer to transport +0ms
engine:ws writing "42["progress",{"progress":99.84186540937002}]" +0ms
engine:ws writing "42["progress",{"progress":99.93823786632886}]" +0ms
Что я здесь делаю неправильно? Есть ли другой способ испускать события с сервера только конкретным клиентам, которых мне не хватает?
Я редактировал свой вопрос, чтобы показать больше базовой архитектуры кода. Я не могу просто испускать соединение, поскольку передаю информацию с другого маршрута в сокет. –
Я отредактировал свой ответ в соответствии с вашим кодом, я объединил 'socket.js' и' s3upload.js' в том же файле, чтобы упростить его. Если вам действительно нужно их разделить, я бы рекомендовал вам переключить зависимость, используя socket.js, импортирующий S3, а не наоборот. Вам нужно будет вызывать функции на основе событий сокета, поэтому ему необходимо будет получить доступ к функциям 's3upload.js'. –
Я попытаюсь перестроить свое приложение с вашими предложениями, спасибо за помощь. Связанный с вами вопрос основывается на вашем предположении о перемещении моего кода: верно ли, что при использовании сокета приложения действительно должны быть созданы вокруг socket.io, чтобы вся логика передавалась через обработчик сокета? Если это правда, не могли ли сделать выделенные маршруты невозможными для записи при использовании сокета? –