Sto utilizzando Node.js per creare un microservizio di caricamento dei media. Questo servizio funziona registrando i dati binari del caricamento in un buffer e quindi utilizzando il pacchetto S3 npm per caricare su un bucket S3. Sto cercando di utilizzare l'eventEmitter presente in quel pacchetto che mostra la quantità di dati caricati su S3, e di inviarlo al client che sta facendo il caricamento (in modo che possano vedere i progressi del caricamento). Sto usando socket.io per questo invio di dati di avanzamento al client.Socket.io Impossibile emettere i dati nella stanza univoca del cliente
Il problema che sto avendo è che l'evento .emit in socket.io invierà i dati di avanzamento del caricamento a tutti i client connessi, non solo al client che ha avviato il caricamento. A quanto ho capito, un socket si connette a una stanza predefinita su 'connection', che è specchiata dall''ID 'sul lato client. Secondo i documenti ufficiali, l'uso di socket.to (id) .emit() dovrebbe inviare i dati con scope solo a quel client, ma questo non funziona per me.
codice Esempio AGGIORNAMENTO:
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);
});
};
Quando si utilizza DEBUG = * node myapp.js, vedo il socket.io-pa rser prendendo in queste informazioni, ma non emette al cliente:
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
Tuttavia, se mi tolgo la parte .to di questo codice, invia i dati al client (sia pure a tutti i clienti, che non aiuterà affatto):
io.sockets.on('connection', function(socket) {
socket.join(socket.id);
socket.emit('progress', {progress: (data.progressAmount/data.progressTotal)*100});
});
debug = * myapp.js nodo:
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
che cosa sto facendo male qui? C'è un modo diverso di emettere eventi dal server solo a client specifici che mi mancano?
Ho modificato la mia domanda per mostrare più dell'architettura di codice sottostante. Non posso semplicemente emettere sulla connessione, dato che sto passando le informazioni da un'altra route nel socket. –
Ho modificato la mia risposta in base al codice, ho unito 'socket.js' e' s3upload.js' nello stesso file per renderlo più semplice. Se hai davvero bisogno di tenerli separati, ti consiglio di attivare la dipendenza avendo socket.js che importa S3 e non viceversa. Dovrai chiamare le funzioni in base agli eventi del socket, quindi dovrà accedere alle funzioni 's3upload.js'. –
Proverò a ri-architettura la mia app con i tuoi suggerimenti, grazie per l'aiuto. Domande correlate basate sul tuo suggerimento per spostare il mio codice: è vero che quando si utilizza il socket, le app dovrebbero davvero essere progettate attorno a socket.io, in modo che tutta la logica sia passata attraverso il gestore di socket? Se ciò è vero, non renderebbe impossibile scrivere percorsi dedicati durante l'utilizzo di socket? –