Docs: Question : Chaînes (api/channels.md) - Accéder à une chaîne sur demande

Créé le 17 déc. 2017  ·  6Commentaires  ·  Source: feathersjs/docs

Salut,

En utilisant des canaux, je ne trouve pas de solution de travail pour ajouter un utilisateur dynamiquement à un canal (par un appel du client)

Par exemple, j'ai essayé sans succès ce code :

(Custom service)

class Service {
  constructor (options) {
    this.options = options || {};
  }
  setup(app) {
    this.app = app;
  }

  async create (data, params) {
    if (Array.isArray(data)) {
      return await Promise.all(data.map(current => this.create(current)));
    }

/*
data.action: "join" or "leave",
data.type: in this case "user",
data.identifier: the user ID or it's username
*/


    this.app.channel(`${data.type}/${data.identifier}`)[data.action](params);

    return data;
  }
}


(Publication)

  app.service('users').publish((data, hook) => {
    // return app.channel('authenticated');
    return [
      app.channel(`user/${data._id}`),
      app.channel(`user/${data.username}`)
    ];
  });

Mais après avoir été correctement ajouté à la liste des connexions du canal en appelant le service personnalisé, je ne reçois pas de mise à jour des publications
J'ai vérifié que le nom des publications de la chaîne et le nom de la chaîne abonnée dynamiquement par l'appel sont les mêmes, mais rien ne s'est passé lorsque l'utilisateur a eu une mutation.
Cependant cela fonctionne avec le canal authenticated .

Je pense que l'argument connection n'est pas exactement le même que l'argument params , et c'est probablement le problème.

Alors, comment ajouter une connexion à un canal lorsque le client le demande ?

Commentaire le plus utile

Si quelqu'un veut un exemple de code :

/* eslint-disable no-unused-vars */

const each = require('lodash.foreach');

class Service {
  constructor (options) {
    this.options = options || {};
  }
  setup(app) {
    this.app = app;
  }

  async create (data, params) {
    if (Array.isArray(data)) {
      return await Promise.all(data.map(current => this.create(current)));
    }

    const channel = `${data.type}/${data.identifier}`;
    const action = data.action;
    if(action === "join"){
      const { connections } = this.app.channel(this.app.channels).filter(connection => {
        return connection.connection_id === params.connection_id;
      });
      console.log('join', params.connection_id, channel);
      each(connections, connection => {
        this.app.channel(channel).join(connection);
      })
    }else if(action === "leave"){
      console.log('leave', params.connection_id, channel);
      this.app.channel(channel).leave(connection => {
        return connection.connection_id === params.connection_id;
      });
    }

    // this.app.channel()[data.action]();

    return data;
  }
}

module.exports = function (options) {
  return new Service(options);
};

module.exports.Service = Service;

Et dans app.js ;

app.configure(socketio((io)=>{
  io.use(function(socket, next) {
    socket.feathers.connection_id = socket.id;
    next();
  });
}))

Parce que mon problème est résolu, je ferme le sujet

Tous les 6 commentaires

L'astuce avec les canaux est qu'ils doivent être représentés par des données qui ont été enregistrées dans la base de données car les canaux eux-mêmes ne sont pas persistants et uniquement locaux sur le serveur Feathers.

Je pense que ce que vous recherchez est similaire à la mise à jour des salles des utilisateurs lorsqu'ils en rejoignent/en quittent une, ce qui pourrait ressembler à ceci :

// Get a user to leave all channels
const leaveChannels = user => {
  app.channel(app.channels).leave(connection =>
    connection.user._id === user._id
  );
};

// Update channels for updated user information
const updateUserChannels = function(user) {
  // Find all connections for this user
  const { connections } = app.channel(app.channels).filter(connection =>
    connection.user._id === user._id
  );

  // Leave all channels
  leaveChannels(user);

  // Re-join all channels with the updated user information
  connections.forEach(connection => {
    app.channel('authenticated').join(connection);
    // Assuming that the chat room/user assignment is stored
    // on an array of the user
    user.rooms.forEach(room =>
      app.channel(`rooms/${roomId}`).join(connection)
    )
  });
}

app.service('users').on('updated', updateUser);
app.service('users').on('patched', updateUser);
app.service('users').on('removed', leaveChannels);

Donc, si vous avez 100 000 connexions et qu'une personne rejoint un nouveau canal, plumes exécute-t-elle cette fonction pour chaque utilisateur ?

Il ne s'exécutera qu'une seule fois chaque fois qu'un utilisateur est mis à jour, corrigé ou supprimé. Les anciennes fonctions de filtrage (v2) fonctionnaient pour chaque connexion, ce qui était la principale raison pour laquelle nous sommes passés au système de canaux (qui est beaucoup plus rapide et plus sécurisé).

Si quelqu'un veut un exemple de code :

/* eslint-disable no-unused-vars */

const each = require('lodash.foreach');

class Service {
  constructor (options) {
    this.options = options || {};
  }
  setup(app) {
    this.app = app;
  }

  async create (data, params) {
    if (Array.isArray(data)) {
      return await Promise.all(data.map(current => this.create(current)));
    }

    const channel = `${data.type}/${data.identifier}`;
    const action = data.action;
    if(action === "join"){
      const { connections } = this.app.channel(this.app.channels).filter(connection => {
        return connection.connection_id === params.connection_id;
      });
      console.log('join', params.connection_id, channel);
      each(connections, connection => {
        this.app.channel(channel).join(connection);
      })
    }else if(action === "leave"){
      console.log('leave', params.connection_id, channel);
      this.app.channel(channel).leave(connection => {
        return connection.connection_id === params.connection_id;
      });
    }

    // this.app.channel()[data.action]();

    return data;
  }
}

module.exports = function (options) {
  return new Service(options);
};

module.exports.Service = Service;

Et dans app.js ;

app.configure(socketio((io)=>{
  io.use(function(socket, next) {
    socket.feathers.connection_id = socket.id;
    next();
  });
}))

Parce que mon problème est résolu, je ferme le sujet

Merci pour votre exemple de code

@ Buom01 Merci pour le code, je

Cette page vous a été utile?
0 / 5 - 0 notes

Questions connexes

Hongbo-Miao picture Hongbo-Miao  ·  14Commentaires

Lutece picture Lutece  ·  11Commentaires

swelljoe picture swelljoe  ·  8Commentaires

Hongbo-Miao picture Hongbo-Miao  ·  10Commentaires

ekryski picture ekryski  ·  20Commentaires