Skip to content

Instantly share code, notes, and snippets.

@aesmail
Last active November 8, 2018 12:11
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save aesmail/3270eab8cdae8f6ff78136ba52925be6 to your computer and use it in GitHub Desktop.
NativeScript + Phoenix Channels

I have been struggling (unnecessarily) to make my NativeScript app work seamlessly with Phoenix Channels.

I'm sure this is not the perfect solution, but after trying a lot of other solutions and none of them worked, this one worked for me like a charm.

I'm using:

  • macOS 10.12.6
  • phoenix 1.3.0
  • NativeScript 3.1.3

1. Install the nativescript-websockets package (current version as of this writing is 1.3.3)

You can do this with tns plugins add nativescript-websockets

2. Copy the phoenix.js that gets generated with a new phoenix project and paste it in your NativeScript project.

You can also download it from https://github.com/phoenixframework/phoenix/blob/master/priv/static/phoenix.js

I pasted the file into a "phoenix" folder. So project_root/phoenix/phoenix.js, but you can put it wherever you want.

3. Remove all browser-related code from phoenix.js which is about 7-9 lines.

Line 739, remove the reference to the window object:

This this.transport = opts.transport || window.WebSocket || LongPoll;

Becomes this.transport = opts.transport || WebSocket || LongPoll;

The nativescript-websockets package provides the WebSocket class.

Comment out the lines from 1165 to 1172.

Those lines are for the if (window.XDomainRequest) { ... } block of code.

They create a browser websocket object which we don't need here after including the nativescript-websockets package.

That's it. You're all set.

Now you can use Phoenix Channels as expected:

require("nativescript-websockets");
var Phx = require("../phoenix/phoenix"); // <- this depends on where you put your file

// to create a socket connection
var socket = Phx.Socket("http://localhost:4000/socket", {params: {userToken: "123"}});
socket.connect();

// to create a channel
channel = socket.channel("room:lobby", {});

// listen for "shout" events
channel.on("shout", payload => {
  // do your own thing
  dialogs.alert(payload.body);
});

// join the channel, with success and failure callbacks
channel.join()
  .receive("ok", resp => console.log("Joined channel successfully", resp) )
  .receive("error", resp => console.log("Failed to join channel", resp) );

// to send messages
channel.push("shout", {body: "This is a shoutout!"});

// to leave a channel
channel.leave();

NOTE: thanks to @pete.k and @markosko from the NativeScript community slack channel for the suggestions and guidance in reaching this solution.

@lyoung83
Copy link

lyoung83 commented Mar 19, 2018

Thanks for putting this out here!
Just linking the un-minified version of the file here

@whossname
Copy link

Phoenix 1.4 release here

@whossname
Copy link

whossname commented Nov 8, 2018

I have a different process for Phoenix 1.4. First in step 1 you replace this line:

var socket = Phx.Socket("http://localhost:4000/socket", {params: {userToken: "123"}});

With this:

var socket = new Phx.Socket("http://localhost:4000/socket", { params: {userToken: "123"}, transport: WebSocket});

Adding the transport argument.

Then you only need to delete the first line of code in step 3, the one that says:

const global = typeof self !== "undefined" ? self : window

With this we are very close to getting it to work straight from npm. Changing that line to this:

if(typeof global === "undefined") {
  var global = typeof self !== "undefined" ? self : window
}

is enough for the existing script to work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment