GithubHelp home page GithubHelp logo

thoov / ember-websockets Goto Github PK

View Code? Open in Web Editor NEW
340.0 13.0 58.0 3.14 MB

Ember.js websockets and socket.io addon

License: MIT License

JavaScript 91.31% HTML 4.84% CSS 0.60% Handlebars 3.25%
websockets ember-addon javascript socket-io ember

ember-websockets's Introduction

ember-websockets

GitHub Actions CI

Compatibility

  • Ember.js v3.24 or above
  • Ember CLI v3.24 or above
  • Node.js v12 or above

Installation

ember install ember-websockets

Usage

Simple example of using it in your app

import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

export default class MyController extends Controller {

  /*
   * 1. Inject the websockets service
   */
  @service('websockets') websockets;
  socketRef = null,

  constructor() {
    super(...arguments);

    /*
      2. The next step you need to do is to create your actual websocket. Calling socketFor
      will retrieve a cached websocket if one exists or in this case it
      will create a new one for us.
    */
    const socket = this.websockets.socketFor('ws://localhost:7000/');

    /*
      3. The next step is to define your event handlers. All event handlers
      are added via the `on` method and take 3 arguments: event name, callback
      function, and the context in which to invoke the callback. All 3 arguments
      are required.
    */
    socket.on('open', this.myOpenHandler, this);
    socket.on('message', this.myMessageHandler, this);
    socket.on('close', this.myCloseHandler, this);

    this.set('socketRef', socket);
  }

  myOpenHandler(event) {
    console.log(`On open event has been called: ${event}`);
  }

  myMessageHandler(event) {
    console.log(`Message: ${event.data}`);
  }

  myCloseHandler(event) {
    console.log(`On close event has been called: ${event}`);
  }

  @action
  sendButtonPressed() {
    this.socketRef.send('Hello Websocket World');
  }
}

Sending messages to the server

const socket = this.socketService.socketFor('ws://localhost:7000/');
socket.send({username: 'foo', didSomeAction: 'pressedAButton'}, true);

// the above line is the same as this:
socket.send(JSON.stringify({username: 'foo', didSomeAction: 'pressedAButton'}));

The send method takes 2 arguments. A message which is passed into the native websockets send method and an optional stringify boolean. This boolean, if set to true, will do a JSON.stringify to the message before passing it to the websocket send method. If you are sending strings it is recommended to pass true.

Reconnecting

import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
import { later } from '@ember/runloop';

export default class MyController extends Controller {
  @service('websockets') socketService;

  constructor() {
    super(...arguments);

    const socket = this.socketService.socketFor('ws://localhost:7000/');
    socket.on('close', this.myOnClose, this);
  }

  myOnClose() {
    const socket = this.socketService.socketFor('ws://localhost:7000/');
    later(this, () => {
      /*
        This will remove the old socket and try and connect to a new one on the same url.
        NOTE: that this does not need to be in a Ember.run.later this is just an example on
        how to reconnect every second.
      */
      socket.reconnect();
    }, 1000);
  }
}

Closing the connection

import Component from '@ember/component';
import { inject as service } from '@ember/service';

export default class MyComponent extends Component {
  @service('websockets') socketService;

  /*
    To close a websocket connection simply call the closeSocketFor method. NOTE: it is good
    practice to close any connections after you are no longer in need of it. A good
    place for this clean up is in the willDestroyElement method of the object.
  */
  willDestroyElement() {
    this.socketService.closeSocketFor('ws://localhost:7000/');
  }
}

Multiple Websockets

import Component from '@ember/component';
import { inject as service } from '@ember/service';

export default class MyComponent extends Component {
  @service('websockets') socketService;

  didInsertElement() {
    const socketOne = this.socketService.socketFor('ws://localhost:7000/');
    const socketTwo = this.socketService.socketFor('ws://localhost:7001/');

    socketOne.on('open', this.myOpenFirst, this);
    socketTwo.on('open', this.myOpenSeconds, this);
  }

  myOpenFirst(event) {
    console.log('Hello from socket one');
  }

  myOpenSecond(event) {
    console.log('Hello from socket two');
  }

  willDestroyElement() {
    const socketOne = this.socketService.socketFor('ws://localhost:7000/');
    const socketTwo = this.socketService.socketFor('ws://localhost:7001/');
    socketOne.off('open', this.myOpenFirst);
    socketTwo.off('open', this.myOpenSecond);
  }
}

Multiple Event Handlers

import Component from '@ember/component';
import { inject as service } from '@ember/service';

export default class MyComponent extends Component {
  socketService: service('websockets'),

  didInsertElement() {
    const socket = this.socketService.socketFor('ws://localhost:7000/');

    socket.on('open', this.myOpenFirst, this);
    socket.on('open', this.myOpenSecond, this);
  }

  myOpenFirst() {
    console.log('This will be called');
  }

  myOpenSecond() {
    console.log('This will also be called');
  }

  willDestroyElement() {
    const socket = this.socketService.socketFor('ws://localhost:7000/');
    socket.off('open', this.myOpenFirst);
    socket.off('open', this.myOpenSecond);
  }
}

Socket.IO Support

First set socketIO to be true in your config/environment.js file:

var ENV = {
  'ember-websockets': {
    socketIO: true
  }
};
import Component from '@ember/component';
import { inject as service } from '@ember/service';

export default class MyComponent extends Component {

  /*
    1. Inject the socketio service
  */
  @service('socket-io') socketIOService;

  /*
    Important note: The namespace is an implementation detail of the Socket.IO protocol...
    http://socket.io/docs/rooms-and-namespaces/#custom-namespaces
  */
  namespace = 'myCustomNamespace',

  didInsertElement() {
    /*
      2. The next step you need to do is to create your actual socketIO.
    */
    const socket = this.socketIOService.socketFor(`http://localhost:7000/${this.namespace}`);

    /*
    * 3. Define any event handlers
    */
    socket.on('connect', this.onConnect, this);
    socket.on('message', this.onMessage, this);

    /*
      4. It is also possible to set event handlers on specific events
    */
    socket.on('myCustomEvent', () => { socket.emit('anotherCustomEvent', 'some data'); });
  }

  onConnect() {
    const socket = this.socketIOService.socketFor(`http://localhost:7000/${this.namespace}`);

    /*
      There are 2 ways to send messages to the server: send and emit
    */
    socket.send('Hello World');
    socket.emit('Hello server');
  }

  onMessage(data) {
    // This is executed within the ember run loop
  }

  myCustomEvent(data) {
    const socket = this.socketIOService.socketFor(`http://localhost:7000/${this.namespace}`);
    socket.emit('anotherCustomEvent', 'some data');
  }

  willDestroyElement() {
    const socket = this.socketIOService.socketFor(`http://localhost:7000/${this.namespace}`);
    socket.off('connect', this.onConnect);
    socket.off('message', this.onMessage);
    socket.off('myCustomEvent', this.myCustomEvent);
  }
}

Please visit: socket.io docs for more details on ember-websocket + socket.io

Detailed explanations of the APIs

SocketFor

Example:

const socket = this.socketService.socketFor('ws://localhost:7000/', ['myOptionalProtocol']);

socketFor takes two arguments: a url, a protocol array (optional), and returns a socket instance from its cache or a new websocket connection if one was not found.

To use a custom namespace, append the namespace to the end of the url.

const socket = this.socketService.socketFor(`ws://localhost:7000/${namespace}`);

On

Example:

const socket = this.socketService.socketFor('ws://localhost:7000/');

socket.on('open', this.myOtherOpenFunction);

on takes 3 arguments: event type, callback function, and context. Event type can be one of the following: 'open', 'message', 'close', and 'error'. Callback function will be invoked when one of the event types occurs.

Off

Example:

const socket = this.socketService.socketFor('ws://localhost:7000/');

let openFunctionReference = this.myOpenFunction.bind(this);

socket.on('open', openFunctionReference);
socket.off('open', openFunctionReference);

off takes 2 arguments: event type, callback function. Event type can be one of the following: 'open', 'message', 'close', and 'error'. The callback will be removed from the event pool and will no longer be invoked.

CloseSocketFor

Example:

this.socketService.closeSocketFor('ws://localhost:7000/');

closeSocketFor takes a single argument, a url, and closes the websocket connection. It will also remove it from the cache. In normal cases you would not have to call this method.

Reconnect

Example:

socket.on('close', event => {
  socket.reconnect();
});

reconnect takes no arguments. It will attempt to create a new websocket connect using the previous url. If the connect is not successful the close event will be triggered.

Live Example

The source code for the live example lives in ember-websockets/tests/dummy

Running tests

NOTE: To get the test to run in PhantomJS I created a mocking library found here: mocking library Note that it is still a work in progress.

Feedback or issues

If you have any feedback, encounter any bugs, or just have a question, please feel free to create a github issue or send me a tweet at @thoov.

FAQ

Recommended backend library/framework

Contributing

See the Contributing guide for details.

License

This project is licensed under the MIT License.

ember-websockets's People

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  avatar  avatar  avatar  avatar

Watchers

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

ember-websockets's Issues

websocket not open / connection

I'm getting an exception on ember 2.2.0 when using the simple hello word example:

Uncaught Error: Assertion Failed: Cannot send message to the websocket while it is not open.

If I put a breakpoint on line 69 websocket-proxy.js then it works ok, otherwise it thinks the websocket is not open and will throw the assert. This leads me to believe it is some kind of timing issue / race condition where the socket is not being retrieved from the cache properly:

_ember['default'].assert('Cannot send message to the websocket while it is not open.', this.readyState() === WebSocket.OPEN);

'.' character in url causing Ember.set error in 2.3

Hey guys, really awesome add-on. I'm having issues getting it set up though.

It looks like because Ember now supports nested getters/setters with '.' notation, the socketFor() function breaks when it tries to add the newly created SocketIOProxy to the cache. Here's the exact error:

Property set failed: object in path "sockets.http://uniteable" could not be found or was destroyed. Error: Property set failed: object in path "sockets.http://uniteable" could not be found or was destroyed.

Version info:

DEBUG: Ember             : 2.3.0+667a2a6b
DEBUG: jQuery            : 1.11.3
DEBUG: Ember Simple Auth : 1.0.0

Super understand that this package wasn't built for 2.3, but wanted to get some advice on working through this.

Do you think it'd efficient to rewrite the socketFor function to allow you to add your own namespace? Like this.socketFor(socketUrl, 'api:pusher'), instead of automatically adding it? Would love some input - I can create a push request for the custom namespaces functionality if you're interested. Thanks.

InvalidStateError when closing and reconnecting

Hi,

i get the following Error in Webbrowser when trying to reconnect or retriev a new websocket, after the old websocket gets closed (by the websocket client itself or the websocket server):

"InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable"

Here is an example. My websocket client is build like the example in the readme. Additionally i have a click-event, that sends a message to my websocket server. When the connection gets close, for example by the websocket server (cause of uncought error), and i try to reconnect or retriev a new websocket, i get the above error.
Curious is, that every time i fire the click-event (after retrieving a new websocket connection), my websocket server register a new user-session (connect) but no incoming message.

Can somebody help me?

passing authorization token

Hi,

Is there a recommended way to be able to pass an authorization token along with every request?

Thanks!
James

socketContexts hash lookup fails if data.currentTarget.url does not contain a trailing slash

In this line: https://github.com/thoov/ember-websockets/blob/master/addon/mixins/sockets.js#L33

...
socketContexts[socketURL] = [{controller: controller, route: this}];
...

you are using the socketURL as a key for the socketContexts hash. But then on this line: https://github.com/thoov/ember-websockets/blob/master/addon/mixins/sockets.js#L54

...
socketContexts[data.currentTarget.url.split('').slice(0, -1).join('')].forEach(function(context) {
    context.controller.send(eventName, data);
});
...

if the data.currentTarget.url does not contain a trailing slash it's cutting the key one char, which results in an error while forEach tries to loop over. Just using the key "as is" fixes the problem.

...
socketContexts[data.currentTarget.url].forEach(function(context) {
    context.controller.send(eventName, data);
});
...

If this is not a expected behaviour I can create a PR to fix this.

Thanks,
Alex

socketFor is not a function

Error while processing route: client.payment.index this.get(...).socketFor is not a function TypeError: this.get(...).socketFor is not a function

  websockets: Ember.inject.service(),
  init: function() {
    this._super.apply(this, arguments);
    var socket = this.get('websockets').socketFor('ws://localhost:8080/');

    /*
     * 3) The final step is to define your event handlers. All event handlers
     * are added via the `on` method and take 3 arguments: event name, callback
     * function, and the context in which to invoke the callback. All 3 arguments
     * are required.
     */
    socket.on('open', function(event){
      console.log(event);
    }, this);
    socket.on('message', function(event){
      console.log(event);
    }, this);
    socket.on('close', function(event) {
      console.log(event);
    }, this);
  },

Uncaught UnrecognizedURLError: /sockets/chatroom

chromium Version 52.0.2743.116 (64-bit)

when i visit:

 http://localhost:4200/sockets/chatroom

i see this error message in the javascript console:

ember.debug.js:4914 Uncaught UnrecognizedURLError: /sockets/chatroom

ember s

[nix-shell:~/Desktop/projects/nixcloud/nixcloud-ember-ws-example/ember-websockets]$ ember s
DEPRECATION: ember-try is now included with ember-cli. Including it in your package.json is unnecessary.
Could not start watchman; falling back to NodeWatcher for file system events.
Visit http://ember-cli.com/user-guide/#watchman for more info.
DEPRECATION: Using the `baseURL` setting is deprecated, use `rootURL` instead.
DEPRECATION: ember-cli-test-loader should now be included as an NPM module with version 1.1.0 or greater.
DEPRECATION: ember-try is now included with ember-cli. Including it in your package.json is unnecessary.
DEPRECATION: ember-cli-test-loader should now be included as an NPM module with version 1.1.0 or greater.
Livereload server on http://localhost:49152
Serving on http://localhost:4200/

Build successful - 1679ms.

Slowest Trees                                 | Total               
----------------------------------------------+---------------------
SourceMapConcat: Concat: Vendor /assets/ve... | 96ms                
SourceMapConcat: Concat: Vendor /assets/ve... | 89ms                

Slowest Trees (cumulative)                    | Total (avg)         
----------------------------------------------+---------------------
Babel (28)                                    | 510ms (18 ms)       
SourceMapConcat: Concat: Vendor /asset... (2) | 186ms (93 ms)       

work without socket.io ?

How to use this addon without socket.io

$ ember server

version: 0.2.7
Error reading socket.io file. Please run `ember g socket-io` first
Error: Error reading socket.io file. Please run `ember g socket-io` first
    at Class.module.exports.included ([project]/node_modules/ember-websockets/index.js:24:13)
    at EmberApp.<anonymous> ([project]/node_modules/ember-cli/lib/broccoli/ember-app.js:312:15)
    at Array.filter (native)
    at EmberApp._notifyAddonIncluded ([project]/node_modules/ember-cli/lib/broccoli/ember-app.js:307:45)
    at new EmberApp ([project]/node_modules/ember-cli/lib/broccoli/ember-app.js:103:8)
    at Object.<anonymous> ([project]/Brocfile.js:5:11)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)

socket.reconnect is not a function

Hi,

I am trying your ember-websockets, and using the reconnect example on https://github.com/thoov/ember-websockets. However I got "socket.reconnect is not a function" when running.

Many thanks,

Mike

Here is the piece of the code,

myCloseHandler: function myCloseHandler(event) {
  console.log('On close event has been called: ' + event);
  var socket = this.get('socketService').socketFor('wss://sense.hellomy.com/ws');
  _ember['default'].run.later(this, function () {
    //reconnect every two seconds;
    socket.reconnect();
  }, 2000);
}, 

Socket.io problem

I am very new to Ember and web development. Thanks for your addon, it works almost great for me! Just a few questions.

  1. In the documentation, under socket.io support section, when you do willDestroyElement(), do you mean to say const socket = this.get('socketIOService').socketFor('http://localhost:7000/'); instead of socketService?

  2. On my server side I setup an setInterval(socket.emit('message', 'some message'), 10000) so that it emits this event every 10 seconds. And on my client side, I have more than one routes, web-socket component is only in the index route. While I do want it to receive the event even if I am not on the index page, I figure that once I navigate to some other pages and navigate back to the index page, I will receive 'message' event multiple times, as if I have more than one sockets. Can you reproduce the problem and take a look? I might have done something wrong, please let me know if you need anything else from me. Thanks!

An in-range update of socket.io is breaking the build 🚨

Version 1.7.1 of socket.io just got published.

Branch Build failing 🚨
Dependency socket.io
Current Version 1.7.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As socket.io is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ


Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details
Release Notes 1.7.1

(following socket.io-client update)

Commits

The new version differs by 1 commits .

  • 797c9a3 [chore]Β Release 1.7.1 (#2768)

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Development environment setup

I've forked the repo and tried to run tests, but I failed. Steps to reproduce:

  1. Clone a fresh master
  2. Run npm install
  3. Run bower install (btw, this one is missing in README)

Result:

  1. ember t gets stuck forever
  2. ember s gives error "Ember Views require jQuery between 1.7 and 2.1" (while jQuery.fn.jquery => "1.12.0")

I also noticed that ember-cli and ember versions are not the most recent ones, so I suspect that there is some disagreement between dependency versions somewhere. If you have some idea what can cause this problem, it would be very nice if you could fix that, since such changes are better made by someone who knows the app. If you have no idea and/or no time to take care of it, please let me know, I'll dig this one on my own.

socket.off() not working with socket.io

ember v2.6.0
ember-websockets v3.0.0

The socket.off() method is not stopping the socket from listening when my component is torn down. After transitioning to another route that does not render this component, it is still listening.

I followed the instructions to a T here: https://www.npmjs.com/package/ember-websockets in setting this project up. I also referenced the instructions here: https://github.com/thoov/ember-websockets/blob/master/docs/socket-io.md but that documentation is over a year old and not very helpful.

Here is an example of the component:

import Ember from 'ember';
export default Ember.Component.extend({

    //Inject the socket.io service into this component.
    io: Ember.inject.service('socket-io'),

    init() {

        //Make sure Ember is able to do important setup work (if any);
        this._super(...arguments);

        let socket = this.get('io').socketFor(`localhost:5000/`);

        //This works because I successfully get updates after the component is rendered.
        socket.on('connect', () => {
            socket.on('update', this.update, this);
        });
    },

    //also tried willDestroy()
    willDestroyElement() { 

        //This fires so I know the component is tearing down properly.
        console.log('willDestroyElement fired');

        //Made sure I am referencing the exact same socket.io namespace as in init().
        let socket = this.get('io').socketFor(`localhost:5000/`);

        //This line does not seem to stop the socket from listening...
        socket.off('update', this.update);
    },

    update(message) {

        //I continue to see this output in the console even after this component has been torn down.
        console.info(message);
    }

});

Am I missing something here?

Wrap sockets with Promise object.

Current behavior:

  1. User needs to emit some changes to the socket.
  2. The socket is not connected yet (readyState == CONNECTING)
  3. emit action does nothing.

Expected behavior.

  1. User needs to emit some changes to the socket.
  2. The socket wrapped with Promise. Socket state is CONNECTING
  3. emit action binds send to promise's resolve handler.

Example (in coffee):

socketPromise = new Ember.RSVP.Promise (resolve, reject) ->
      websocket = new WebSocket(socketURL)
      websocket.onopen -> resolve(websocket)
      websocket.onerror (error)-> reject(error)

socketPromise.then (socket)=>
  socket.send(data)

With this approach we can be sure that our message will be sent, even if we proceed emit before connection actually opened.

What do you think?

UPD: I know, we can use onopen action, but I believe ember-way it to use promises (same way it did in DS)

Uncaught ReferenceError: io is not defined

I had ember-websockets running, everything was fine. Then I wanted to run my ember application on another device. There I got the following error in the browser:

socket-io.js:12 Uncaught ReferenceError: io is not defined at Class.createSocket (http://localhost:4200/assets/vendor.js:85187:25) at Class.socketFor (http://localhost:4200/assets/vendor.js:85253:31) ...

In the line
var newSocketIO = io(url, options);

I was wondering why it worked on my initial device. So I removed the node_modules folder and then it occurred there as well.

When I enter ember install ember-websockets
I get
Installed packages for tooling via npm. installing ember-websockets install package mock-socket Installed packages for tooling via npm. install bower package urijs cached https://github.com/LearnBoost/socket.io-client.git#1.7.1 cached https://github.com/medialize/URI.js.git#1.18.3 Installed browser packages via Bower. Installed addon package.

ember g socket-io

returns

installing socket-io install bower package socket.io-client cached https://github.com/medialize/URI.js.git#1.18.3 cached https://github.com/LearnBoost/socket.io-client.git#1.7.1

So it seems that everything is installed properly.

I would have thought that ember-websocket takes care of resolving the dependency to socket-io itself so that I don't have to do something manually. What do I have to do in order to resolve that issue?

Attempting to inject an unknown injection: `service:socket-io`

I did exactly as it is told in https://github.com/thoov/ember-websockets/blob/master/docs/socket-io.md

In fact, my controller looks like this:

"use strict";

import Ember from 'ember';

export default Ember.Controller.extend({

    socketIOService: Ember.inject.service('socket-io'),

    init: function() {
        this._super.apply(this, arguments);
        var socket = this.get('socketIOService').socketFor('http://localhost:5000/');
    }
});

When I open the corresponding route the console output is as follows:

Attempting to inject an unknown injection: service:socket-io

Using ember 2.7.0

An in-range update of ember-cli-htmlbars is breaking the build 🚨

Version 1.1.1 of ember-cli-htmlbars just got published.

Branch Build failing 🚨
Dependency ember-cli-htmlbars
Current Version 1.1.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As ember-cli-htmlbars is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ


Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details
Commits

The new version differs by 10 commits .

  • 3a16f2e 1.1.1
  • 3f96e00 Merge pull request #103 from ember-cli/travis
  • a4eaf77 CI: Simplify config file
  • 5f8cd7c Merge pull request #102 from ember-cli/greenkeeper/remove-node-0.10
  • 2fa8b83 CI: Update NodeJS targets
  • b2db424 chore: drop support for Node.js 0.10
  • f44d4b8 Merge pull request #98 from ember-cli/locks-patch-1
  • e83a393 Update ember-addon-main.js
  • 8428c86 Merge pull request #96 from ember-cli/greenkeeper-broccoli-concat-2.3.6
  • af9011e chore(package): update broccoli-concat to version 2.3.6

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

setupController conflicts with ember-websockets

I'm using the following code: https://gist.github.com/vhf/4080d7377b7c4f6c2859

Somehow, this does not work because of setupController. onopen does not log anything.

When I comment out the whole setupController, onopen logs correctly. I tried commenting out both setupController lines individually with no luck. As long as there is a setupController in my route, ember-websockets does not work.

[EDIT]
I forgot to mention that I'm using ember-cli with following versions:

Ember             : 1.9.0
Ember Data        : 1.0.0-beta.12
Handlebars        : 2.0.0
jQuery            : 1.11.1
Ember Simple Auth : 0.7.2

Socket.IO adapter doesn't clean up on disconnect.

The Socket.IO adapter doesn't clean up on the disconnect event. This means that all the events that are created inside the on('connect') is going to be fired multiple times, because they are going to be created again each time the app reconnects.

A simple example:

  1. Connect ember application to a server(node etc.) with the socket.io adapter.
  2. put a console.log inside an event etc. on('welcome')
  3. Fire the welcome event each time the clients connect.
  4. Restart node server
  5. Watch N+1 console.log each time you reconnect

TLDR; This problem isn't that on('connect') is fired multiple times. But that the previous created listeneres inside the connect event isn't destroyed on disconnect.

Unexpected behavior when using emit() with four arguments

The socket.io socket.emit() method accepts an arbitrary number of arguments.

Ember-websockets should support the same functionality, and in most cases it does. However, when four arguments are passed to SocketIOProxy.emit() the method assumes the third argument is a function and the fourth is the context. This means calling SocketIOProxy.emit() with four arguments, but without an acknowledgement function and context will not work. 😞

socket event listeners are not camelCased

onopen, onerror, etc, should be camelCased both for ease of use/reading and because the examples show action methods being defined with these names, so it violates generally accepted style guides

The `ember generate` command failed on installation

When I execute "ember install ember-websockets" on my brand new ember-cli application, my output is the following

version: 0.2.3
0.2.3

Installed packages for tooling via npm.
installing
Installing browser packages via Bower...
not-cached git://github.com/medialize/URI.js.git#*
resolved git://github.com/medialize/URI.js.git#1.15.0
Installed browser packages via Bower.
installing
The ember generate command requires an entity name to be specified. For more details, use ember help.

Am I doing something wrong ?

Bug: Incorrect OFF on socket.io events

Hi, first of all thank you for the addon.
I noticed there is a bug on the socket.io proxy OFF method. On line: https://github.com/thoov/ember-websockets/blob/master/addon/helpers/socketio-proxy.js#L38
The correct way to check the socket.io url is this.socket.io.uri instead of this.socket.io.url:

const listeners = this.listeners.filter(listener => listener.callback === callback && listener.url === this.socket.io.url && listener.type === type);

Should be:

const listeners = this.listeners.filter(listener => listener.callback === callback && listener.url === this.socket.io.uri && listener.type === type);

PS: On line https://github.com/thoov/ember-websockets/blob/master/addon/helpers/socketio-proxy.js#L32 you are checking it correctly.

Cannot reconnect after closeSocketFor()

I have a socket set in one of my components and I have the following set:

willDestroyElement: function() {
    this.get('socketIOService').closeSocketFor(this.get('socketPath'))
}

If I dont close the socket this way when transitioning I get the following error:

Uncaught Error: Assertion Failed: calling set on destroyed object

Whats happening is that my socket connection is still listening for events from the API and its trying to call methods to set properties that were destroyed when I transitioned to another route.

So when I close the socket and return to the route it fails to reconnect. Heres my socket setup:

socketSetup: (function () {
      var socket, socketPath;
      socket = this.get('socket');
      socketPath = this.config.Variables.API_URL + '/service/' + this.get('service.id');
      socket = this.get('socketIOService').socketFor(socketPath);
      this.set('socketPath', socketPath);
      console.log('TRYING TO CONNECT', this.get('socketIOService'));

     socket.on('close', function (closeData) {
        console.log('CLOSE DATA', closeData);
        return socket.reconnect();
      });

      socket.on('connect', function (event) {
        // This does not fire when returning to the route
        console.log('CONNECTING');
        socket.on('computerAvailable', this.computerAvailable, this);
        socket.on('computerUnavailable', this.computerUnavailable, this);
        socket.on('portalAvailable', this.portalAvailable, this);
      }, this);

      socket.on('open', function (openData) {
        return console.log('OPENING', openData);
      }, this);

      socket.on('close', function (closeData) {
        return console.log('CLOSING', closeData);
      }, this);

      socket.on('error', function () {
        console.log('CONNECTION ERROR');
        return this.disruptedFeature;
      }, this);

      socket.on('disconnect', this.disruptedFeature, this);

      socket.on('reconnect', function (reconnect) {
        console.log('RECONNECT EVENT');
        this.set('reconnectAttemptCounter', 0);
        return this.featureReconnect(reconnect);
      }, this);

      socket.on('reconnect_attempt', function (attempt) {
        console.log('RECONNECT ATTEMPT');
        this.incrementProperty('reconnectAttemptCounter');
        if (this.get('reconnectAttemptCounter') < this.get('reconnectAttemptLimit')) {
          return this.disruptedFeature(attempt);
        }
      }, this);

      socket.on('reconnect_error', function (error) {
        console.log('RECONNECT ERR');
        if (this.get('reconnectAttemptCounter') > this.get('reconnectAttemptLimit')) {
          return this.featureUnavailable(error);
        }
      }, this);

      return socket.on('reconnect_failed', this.featureUnavailable, this);
    }).on('init')

Any ideas on how to reconnect?

Using socket.io service forces url to /socket.io

Hi there !

I've integrated ember-websockets to use it in my ember project. But when using the socket-io service, the URI i use, is replaced. My code is the following :

import Ember from 'ember';

export default Ember.Controller.extend({
  /*
   * 1) First step you need to do is inject the websocket service into your object. You
   * can inject the service into component, controllers, object, mixins, routes, and views.
   */
  socketService: Ember.inject.service('socket-io'),

  init: function() {
    this._super.apply(this, arguments);

    /*
     * 2) The next step you need to do is to create your actual websocket. Calling socketFor
     * will retrieve a cached websocket if one exists or in this case it
     * will create a new one for us.
     */
    var socket = this.get('socketService').socketFor('ws://10.112.244.221:8080/ws');

    /*
     * 3) The final step is to define your event handlers. All event handlers
     * are added via the `on` method and take 3 arguments: event name, callback
     * function, and the context in which to invoke the callback. All 3 arguments
     * are required.
     */
    socket.on('connect', this.myOpenHandler, this);
    socket.on('message', this.myMessageHandler, this);
    socket.on('close', function(event) {
      console.log("event = ", event);
    }, this);
  },

  myOpenHandler: function(event) {
    console.log('On open event has been called: ', event);
    var socket = this.get('socketService').socketFor('ws://10.112.244.221:8080/ws');
    socket.send('PING');
  },

  myMessageHandler: function(event) {
    console.log('Message: ', event.data);
  },

  /*
   * To close a websocket connection simply call the closeSocketFor method. NOTE: it is good
   * practice to close any connections after you are no longer in need of it. A good
   * place for this clean up is in the willDestroy method of the object.
   */
  willDestroy() {
    this.get('socketService').closeSocketFor('ws://10.112.244.221:8080/ws');
  }
});

On runtime the url called is http://10.112.244.221:8080/socket.io. Have you already had this case ?
I'm using spring-websocket for the socket backend.

Thanks in advance.

Regards,

reconnect

is there a way to retry reconnection ?

An in-range update of ember-data is breaking the build 🚨

Version 2.10.0 of ember-data just got published.

Branch Build failing 🚨
Dependency ember-data
Current Version 2.9.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As ember-data is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ


Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build failed Details
Commits

The new version differs by 65 commits (ahead by 65, behind by 25).

  • bda9732 Release Ember Data 2.10.0
  • a22a702 Update changelog for the Ember Data 2.10.0 release
  • f13827b Release Ember Data v2.10.0-beta.3
  • 9ad22ce Update changelog for the Ember Data 2.10.0-beta.3 release
  • 7231263 [PERF] fix sub-optimal compiler output (#4655) (#4656)
  • f3df538 Release Ember Data 2.10.0-beta.2
  • c6aefe7 Update Changelog for the Ember Data 2.10.0-beta.2 release
  • 31480e1 [DOC] Add documentation for query#update() to refresh query
  • 2b56fdf Release 2.10.0-beta.1
  • 7a4beb0 Update changelog for the 2.10.0-beta.1 release
  • 6d8e81b Update changelog for Ember Data 2.10.0-beta.1
  • 9593e17 Merge pull request #4578 from runspired/fix/null-id-assertions
  • 2d464dc fix assertion tests
  • 58baca4 fix id in error message
  • 97daea8 improved error messaging

There are 65 commits in total. See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Existing proxy reuse does not create new listeners

It seems that when you call socketFor second time for the same url (after the connection has been closed), proxy instance is reused, and new Websocket is assigned to it, but new listeners are not setup for new Websocket (this is done in proxy's setupInternalListeners, which is called only on init and in reconnect method).

This is the code:

    if (existingProxy) {
      /*
        If there is an existing socket in place we simply update the websocket object and not
        the whole proxy as we dont want to destroy the previous listeners.
      */
      existingProxy.socket = newWebSocket;
      return existingProxy;
    }

Simply replacing socket is not enough, as new set of listeners must be setup on the socket object itself, like it is done in reconnect method.

  reconnect() {
    this.set('socket', new WebSocket(this.socket.url, this.get('protocols')));
    this.setupInternalListeners();
  },

Maybe add reconnect(newSocket), or other possibility is to call reconnect instead of replacing socket instance manually, which will setup new socket instance along with listeners.

And in addition, this replacing should be done with existingProxy.set('socket', newWebSocket), not with plain assignment (or it can cause problems with computed properties based on socket, if one would use them).

And one more, when replacing socket instance with new, maybe old socket's listeners must be also cleaned up?

Improved documentation

Update the README and create a /docs folder which has more details explanations of examples, etc.

Can't use ember-websockets as an addon dependency.

I want to create new addon which will depend on ember-websockets addon. Here are steps which I tried.

  1. Create new addon ember-example-addon .
  2. Install ember-websockets addon in ember-example-addon with current command
$ ember install ember-websockets
  1. Move "ember-websockets": "6.1.0" from devDependencies to dependencies in ember-example-addon .

Want to compile ember-example-addon it trows npm error.

The Broccoli Plugin: [SourceMapConcat: Concat: Vendor /assets/vendor.js] failed with:
Error: ENOENT: no such file or directory, stat '/home/vazgen/tmp/ember-addon-with-websocket/tmp/source_map_concat-input_base_path-f0BcKngS.tmp/0/undefined/urijs/src/URI.min.js'

The reason is that In ember-websockets index.js "included " function's app.bowerDirectory gives undefined.

Cant find solution. Can anyone help me.

Uncaught ReferenceError: io is not defined

I am using ember-websockets v4, mock-socket v3 in my application. I am able to connect to the socket(in server) successfully from other applications. When I used ember-sockets, I am getting io is not defined error.
Stack error,
Inside services/socket-io.js file

createSocket: function createSocket(url) {
      var options = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

      var newSocketIO = io(url, options);
      newSocketIO.connect();
      return newSocketIO;
    },

duplicated events when using {{input}}

When I call socket.send and in the action I'm using values from {{input}} I receive duplicated messages from the server.

But if, in the action, I get the values using JQuery it works as expected.
See test app here

Reconnect inside socketFor

At present, socketFor can return closed Websockets and I think that's a bug. The reason is that https://github.com/thoov/ember-websockets/blob/master/app/services/websockets.js#L60-L67 does not check if the socket in the existing proxy is actually open before returning it.

Adding something like:

      if (isWebSocketOpen(existingProxy.socket)) {
        return existingProxy.socket;
      }

      existingProxy.socket.reconnect();

      return existingProxy.socket;

When seeing that an existingProxy is available would fix the problem.

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.