Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Files communication with coffeescript

When I create a new coffeescript file, I cannot access the code in the compiled code from another file because it gets wrapped in some function scope. For example:

CoffeeScript:

class ChatService
  constructor: (@io) ->

Generated Javascript:

(function() {
  var ChatService;    
  ChatService = (function() {    
    function ChatService(io) {
      this.io = io;
    }    
    return ChatService;    
  })();    
}).call(this);

When trying to call ChatService in another file, it's not defined. How do I handle multiple files with coffeescript?

like image 541
Shawn Mclean Avatar asked Feb 15 '12 03:02

Shawn Mclean


2 Answers

Depending on whether this is client- or server-side code, there are two slightly different approaches.

Client-side: Here we attach things that should be available across files to the global namespace (window) as follows:

class window.ChatService
  constructor: (@io) ->

Then, in another file both ChatService and window.ChatService will allow access to the class.


Server-side: Here we must use exports and require. In the ChatService.coffee file, you would have the following:

class exports.ChatService
  constructor: (@io) ->

Then, to get at it from another file you can use:

ChatService = require('ChatService.coffee').ChatService

Note: If there are multiple classes that you are getting from ChatService.coffee, this is one place where CoffeeScript's dict unpacking really shines, such as:

{ChatService, OtherService} = require('ChatService.coffee')

Both: Basically, we choose whether to run server-side or client-side code based on which environment we're in. A common way to do it:

class ChatService
  constructor: (@io) ->

if typeof module != "undefined" && module.exports
  #On a server
  exports.ChatService = ChatService
else
  #On a client
  window.ChatService = ChatService

To get it:

if typeof module != "undefined" && module.exports
  #On a server
  ChatService = require("ChatService.coffee").ChatService
else
  #On a client
  ChatService = window.ChatService

The else clause of the second block can be skipped, since ChatService already refers to the reference attached to window.

If you're going to define a lot of classes in this file, it may be easier to define them like:

self = {}

class self.ChatService

And then attach them like module.exports = self on the server and _.extend(window, self) on the client (replace _.extend with another extend function as appropriate).

like image 193
Aaron Dufour Avatar answered Oct 19 '22 02:10

Aaron Dufour


The usual approach is to define a global namespace in window:

window.App = { }

That would go somewhere in your application's initialization code before anything else happens. And then, for your class:

class App.ChatService
  constructor: (@io) ->

That allows you to reference your class through App anywhere you want and you don't have to worry about polluting the global namespace:

chatter = new App.ChatService

If you wanted to make your ChatService truly global then you could use class window.ChatService but I'd recommend against that except in the most trivial of applications.

AFAIK, node.js has something similar to window but I'm not familiar enough with node.js to tell you what it is.

like image 36
mu is too short Avatar answered Oct 19 '22 01:10

mu is too short