Coder Social home page Coder Social logo

ember-cable's Introduction

ember-cable

This add-on enables simple integration of Rails Action Cable into Ember apps.

CI Ember Observer Score

Installation

run the following command from inside your ember-cli project:

ember install @algonauti/ember-cable

Basic Usage

Once the addon is installed, the cable service can be injected wherever needed in the application.

// tests/dummy/app/components/notification-messages/component.js
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { debug, inspect } from '@ember/debug';
import EmberObject from '@ember/object';
import { getOwner } from '@ember/application';

export default class NotificationMessagesComponent extends Component {
  @service cable;
  @service notification;

  constructor() {
    super(...arguments);
    this._setupConsumer();
  }

  _setupConsumer() {
    let consumer = this.cable.createConsumer('ws://localhost:4200/cable');

    consumer.createSubscription('BroadcastChannel', {
      connected() {
        debug('BroadcastChannel#connected');
        this.perform('ping');
      },
      received(data) {
        debug( "received(data) -> " + inspect(data) );
      },
      disconnected() {
        debug("BroadcastChannel#disconnected");
      }
    });

    // Passing Parameters to Channel
    let subscription = consumer.createSubscription({ channel: 'BroadcastChannel', room: 'BestRoom' }, {
      connected() {
        this.perform('ping', { foo: 'bar' });
      },
      received: (data) => {
        this._updateRecord(data);
      },
      disconnected: () => {
        this.notification.notify("BroadcastChannel#disconnected");
      }
    });

    // Using mixin and inject your services:
    let subscriptionHandler = EmberObject.extend({
      notification2: service('notification'),

      connected() {
        this.notification2.notify("subscriptionHandler#connected");
      },
    }).create(getOwner(this).ownerInjection());

    consumer.createSubscription({ channel: 'BroadcastChannel' }, subscriptionHandler);

    setTimeout(() => {
      subscription.perform('ping', { foo: 'bar' });
    }, 3000);

    setTimeout(() => {
      this.cable.destroy();
    }, 9000);

  }

  _updateRecord(data) {
     debug( "updateRecord(data) -> " + inspect(data) );
   }
}

Contributing

See the Contributing guide for details.

License

ember-cable is released under the MIT License.

ember-cable's People

Contributors

algodave avatar asux avatar baseballlover723 avatar cibernox avatar dependabot[bot] avatar dodeja avatar dubistkomisch avatar ember-tomster avatar glarregle avatar gsilis avatar igorrkurr avatar jasonmit avatar joostverdoorn avatar jurgenwerk avatar newyork-anthonyng avatar rmachielse avatar safeforge avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

ember-cable's Issues

ReferenceError: WebSocket is not defined

This arose while trying to implement ember-fastboot. It seems that WebSocket is created but the ws library for it is not required or included, namely on this line: ember-cable/core/connection.js:19:1

Constant reconnections

I'm seeing the cable websocket connection get dropped and re-established approximately once every 10s.

I had foolishly been languishing on my own branch until today thus I've only just updated my app to use the latest version. I suspect this may be related to the refactor that moved connection_monitor into a separate package, and/or changes relating to init, but haven't had a chance to investigate any deeper. As far as I can tell by looking at the diffs this is the only change that could be causing this problem - it feels like the connection monitor isn't properly detecting that the cable has been opened successfully.

Multiple `connected` hooks firing?

Hi, ActionCable n00b here; taking this addon for a spin and seeing that "connected" seems to fire twice for a single subscription. Is this everyone else's experience too? Perhaps just an ActionCable server bug?

Issue unsubscribing from a channel

I connect to a channel from my Ember application like this...

const consumer = this.cable.createConsumer('ws://localhost:4200/websocket');
const subscription = consumer.subscriptions.create({ channel: "StationChannel", station_id: "1" }, {
  connected() {
    console.log("connected");
  },
  disconnected() {
     console.log("disconnected");
   }
});

this.subscription = subscription;
this.consumer = consumer;

And in Rails it logs

StationChannel is transmitting the subscription confirmation
StationChannel is streaming from station_1

But if I want to disconnect via the Ember application I can't seem to find the right way to do it.

I've tried using unsubscribe from subscription.js like this

this.subscription.unsubscribe();

And by using the remove directly like this

this.consumer.subscriptions.remove(this.subscription);

But I get this same error from Rails with either approach

Unsubscribing from channel: {"channel":"StationChannel","station_id":"1"}
Could not execute command from ({"command"=>"unsubscribe", "identifier"=>"{\"channel\":\"StationChannel\",\"station_id\":\"1\"}"}) [ArgumentError - comparison of String with 0 failed]: /opt/rubies/ruby-2.6.3/lib/ruby/2.6.0/logger.rb:457:in `<' | /opt/rubies/ruby-2.6.3/lib/ruby/2.6.0/logger.rb:457:in `add' | /my-app/app/channels/station_channel.rb:7:in `unsubscribed' | /home/vagrant/.gem/ruby/2.6.3/gems/actioncable-6.0.0.rc1/lib/action_cable/channel/base.rb:192:in `block in unsubscribe_from_channel' | /home/vagrant/.gem/ruby/2.6.3/gems/activesupport-6.0.0.rc1/lib/active_support/callbacks.rb:112:in `block in run_callbacks'

Is this a bug? Any help much appreciated!

Pass the main container to the ember-cable objects

I have trouble using your package when trying to access application services from my subscription object. I can't call service.inject() from my subscription objects.

In your README examples, you creates your channel subscriptions directly into the ember component / controller / service. The javascript object you are passing is able to call the application services because the object capture the context around him. So you are able to access this variable etc...

I have a slightly different approach, I have a Mixin :

import Ember from "ember";

const { debug, Mixin } = Ember;

export default Mixin.create({
  store: inject.service(),

  isConnected: false,

  connected() {
    this.set("isConnected", true);
  },

  disconnected() {
    this.set("isConnected", false);
  },

  received(data) {
    this.get("store").pushPayload(data);
  },
});

I pass it to your cable service t:

// My channel builder service
channelInfo = "MyRailsChannel";
channelMixin = MyRailsSubscription;
return this.get("consumer").subscriptions.create(channelInfo, channelMixin);

This could work but I experience an issue telling me :

Assertion Failed: Attempting to lookup an injected property on an object without a container, ensure that the object was instantiated via a container.

I appears that your objects (Comsumer, Subscriptions, Subscription) aren't linked to the main container of the application, the App container, which prevent me from calling services inside my subscription objet.

The solution is to pass Ember.getOwner(this).ownerInjection() everywhere you create your objects.

Example, in your createConsumer function :

createConsumer(url) {
  return Consumer.create(Ember.getOwner(this).ownerInjection(), { url: url });
}

What do you think ?

Endless `poll` loop doesn't play well with tests

The endless poll makes it that tests never end. It would be good to find a way to only perform one poll for instance when in the testing environment. This I think will enable true component integration tests with something like mock-socket.

I can come up with a PR if you think this is a good idea.

Ability to access active subscriptions

Currently, there is no way to access subscriptions that was created.
For instance, I've created a new Notifications subscription in application controller. There I can handle only received data. But what if I want to to send data to same subscription channel, but form another entity, like form my-notification component for example. Of course, we can create action in application controller and pass it to component, but there could lot of nested controllers/components, that could make code not very tidy.
And since we have cable in form of Service, that would be good to have sort of active subscriptions in it, to be able easily access any subscription application wide.
Hope that would be useful ๐Ÿ˜„

Ability to completely disconnect from websockets

Hey there,
Is there a way to have the cable connection not attempt to reconnect after a set number of retries after getting disconnected? I see in the ConnectionMonitor you continuously poll() but there is no way to stop it.

Cheers,
Carlos

this.perform is undefined

import Ember from 'ember';

export default Ember.Controller.extend({
  authentication: Ember.observer('applicationRoute.authentication', function () { //executed after dom loaded
    if (this.get("applicationRoute.authentication")) {
      this.createNotificationSubscription();
      this.createUserAppearSubscription();
    } else {
      this.removeSubscription();
    }
  }),
  createConsumer(){
  },
  createNotificationSubscription(){
  },
  createUserAppearSubscription(){
  },
  removeSubscription(){
  },
  handleActionCable(){
    const context = this;
    this.createConsumer = function () {
      return context.cableService.createConsumer('ws://localhost:3000/cable?token=' + context.commonService.getToken());
    };
    this.createUserAppearSubscription = function () {
      context.createConsumer().subscriptions.create('UserappearanceChannel', {
        connected: () => {
          context.debug(this);
          context.debug(context);
          this.perform('appear', 'helll!');
        },
        disconnected: () => {
          alert("connect");
        },
        received: (data) => {
          context.commonService.showCustomNotification(data.message, data.link);
        }
      });
    };
    this.createNotificationSubscription = function () {
      context.createConsumer().subscriptions.create({
        channel: 'NotificationChannel',
        user_id: context.commonService.getId()
      }, {
        received: (data) => {
          context.commonService.showCustomNotification(data.message, data.link);
        }
      });
    };

    this.removeSubscription = function () {
      context.createConsumer().subscriptions.remove({
        channel: 'NotificationChannel',
        user_id: context.commonService.getId()
      });

      context.createConsumer().subscriptions.remove({
        channel: 'UserappearanceChannel'
      });
    };
  },
  init(){ //executed first & only at once
    Ember.run.scheduleOnce('afterRender', this, function () {
      this.handleActionCable();
    });
  }
});

the websocket is fine but i got undefined in perform method in createUserAppearSubscription(), running this via fastboot

Problem with cookies.signed

Is this working the same way as action_cable.js? I mean I can't setup current user on Rails side via cookies.signed

Additional parameters in subscriptions create

Hi! ;) As I see there is no option here to send additional parameters when creating new subscription. On backend there is a way to fetch additional parameters, for example:
stream_from "chat_#{params[:room]}". I need this option to send user id and create channel for each user. I think it's a great feature and I would be very grateful if you add it.

Problems with Ember-CLI 2.14.0

After I upgraded my project from 2.12.0 to 2.14.0, I got the following error:

[20:43:35] jurgen:formaviva-web git:(master*) $ ember s
Livereload server on http://localhost:49153
'instrument' is imported from external module 'ember-data/-debug' but never used
The Broccoli Plugin: [BroccoliMergeTrees: TreeMerger: `addon/` trees] failed with:
TypeError: ember-cable/core/connection.js: pluginList.indexOf is not a function
    at Parser.loadPlugins (/Users/jurgen/development/formaviva-web/node_modules/babylon/lib/index.js:1620:20)
    at new Parser (/Users/jurgen/development/formaviva-web/node_modules/babylon/lib/index.js:1573:27)
    at Object.parse (/Users/jurgen/development/formaviva-web/node_modules/babylon/lib/index.js:7246:10)
    at Object.exports.default (/Users/jurgen/development/formaviva-web/node_modules/ember-cable/node_modules/babel-core/lib/helpers/parse.js:36:18)
    at File.parse (/Users/jurgen/development/formaviva-web/node_modules/ember-cable/node_modules/babel-core/lib/transformation/file/index.js:574:40)
    at File.parseCode (/Users/jurgen/development/formaviva-web/node_modules/ember-cable/node_modules/babel-core/lib/transformation/file/index.js:691:20)
    at /Users/jurgen/development/formaviva-web/node_modules/ember-cable/node_modules/babel-core/lib/transformation/pipeline.js:167:12
    at File.wrap (/Users/jurgen/development/formaviva-web/node_modules/ember-cable/node_modules/babel-core/lib/transformation/file/index.js:639:16)
    at Pipeline.transform (/Users/jurgen/development/formaviva-web/node_modules/ember-cable/node_modules/babel-core/lib/transformation/pipeline.js:165:17)
    at /Users/jurgen/development/formaviva-web/node_modules/ember-cable/node_modules/broccoli-babel-transpiler/lib/parallel-api.js:102:26

Destroy consumers

Hi, @algonauti
First of all thanks for this library, you safe my time.

I have the issue with destroy consumers or unsubscribe. I have many pages and component at the app, and when change url, I destroy components and do not need cable updates.

How can i do it with you library?

Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.

Hi,

First of all thanks for your work, it's a nice package you made here :)

However, I am experiencing an issue regarding the CONNECTING state.

Everything works fine, I am actually recieving and sending messages from the server. However it seems the connecter try to send messages whereas the WebSocket isn't fully connected.

Maybe the this.isOpen() is not returning the right answer ?

Info

  • ember-cli: 2.8.0
  • node: 7.4.0
  • os: darwin x64
  • ember-cable: 0.5.0

Backtrace

Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
    at Class.send (http://cad.dev/assets/vendor.js:94112:31)
    at Class.send (http://cad.dev/assets/vendor.js:94284:30)
    at Class.sendCommand (http://cad.dev/assets/vendor.js:94416:30)
    at http://cad.dev/assets/vendor.js:94360:15
    at Array.forEach (native)
    at Class.reload (http://cad.dev/assets/vendor.js:94359:33)
    at Class.open (http://cad.dev/assets/vendor.js:94176:44)
send @ connection.js:16
send @ consumer.js:14
sendCommand @ subscriptions.js:87
(anonymous) @ subscriptions.js:31
reload @ subscriptions.js:30
open @ connection.js:80

Error location

send: function send(data) {
  if (this.isOpen()) {
    this.get('webSocket').send(JSON.stringify(data));    # <=
  }
},

Edit

  1. Add ember environment information

Closing connection

Hi guys, I am struggling to find a way to disconnect the web socket when I no longer need it.
Do I simply call destroy on the consumer which in turn will call willDestroy ?

Publish v1.1.0 to NPM

Hi,

Is it possible to publish the latest version of this package to NPM? The latest on NPM is a few years old. Currently I'm putting this into my package.json:

"ember-cable": "github:algonauti/ember-cable#v1.1.0",

Thanks!

ember-cable seems to be disconnecting and connecting

WebSocket implementation from ember-cable seems to be disconnecting and connecting.

It should only automatically reconnect if the connection is dropped. Currently it seems every 5 seconds, ember-cable is making a new websocket connection and then after 1 second it disconnecting the existing connection to use the new connection.

I made a repo describing this problem. It includes rails api and ember.

https://github.com/sunapi386/chatroom

Error when extracting actioncable package

I am getting the following error when deploying the project:

Error extracting /app/.npm/@rails/actioncable/6.0.2/package.tgz archive: ENOENT: no such file or directory, open '/app/.npm/@rails/actioncable/6.0.2/package.tgz

I am not sure if it's due to an incorrect dependency reference inside the project, or an issue with the npm registry itself

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.