Comet (long polling) for all browsers using ScriptCommunicator

Plurk Comet

There's little information on the web how to implement comet (long polling) so it works across domains and works in all major browsers.

I am sharing my solution that's used to power comet on Plurk and I hope this can save time for anyone that has to implement something similar.

I have pushed ScriptCommunicator on github and this script can do following stuff:

  • uses script tags for communication, but can detect when a script isn't loaded (this is non-trivial to implement across browsers)
  • works across domains as long as you control the domains
  • works on IE 6, IE 7, IE 8, FF X, Safari, Chrome and Opera
  • small (80 lines of code) with no dependencies

ScriptCommunicator can also be used to do JSONP calls in a manner where you can handle errors properly. ScriptCommunicator is copyrighted by Plurk Inc. and released under the BSD license.

The problem

There are different problems associated with long polling:

  • scaling comet by using one domain is a lot more difficult than scaling it by using different domains
  • most browsers limit how many open connection you can have to one domain
  • AJAX communication between different domains is restricted due to same origin policy

To solve this we use script tags for communication and this has one big pitfall: you can't easily find out whatever a script is sourced properly - - so error handling using script tags becomes a lot more difficult. ScriptCommunicator adresses these issues and makes communication easy.

The hack

It's trivial to source scripts across domains (you simply append the SCRIPT tag to the head or the body). What's not trivial is finding out if the script was sourced properly and handling errors - and I haven't found a solution for this problem on the net. But there is a solution and it works like this:

  • for Internet Explorer we use script_tag.onreadystatechange to figure out if a success signal is set
  • for other browsers we use following knowledge: sourcing JavaScript is blocking, this means we append two script tags to the document where the first one is sourcing the JavasScript and the second one checks if a success signal is set

It's hacky, but it works :-)

How to use it

You source JavaScript from another domain and this domain does a callback to foocall function. You also supply two functions on_success and on_error.

var url = 'http://some_domain.com/give_me_js_back.php?i=42&callback=foocall'
ScriptCommunicator.sourceJavascript(url, on_success, on_error)

Either your external JavaScript or foocall sets following attribute to true (to signal that the loading of the script was succefull):

ScriptCommunicator.callback_called = true;

That's basically it! Visit ScriptCommunicator on github to get the code.

If you are interested in comet check out following amix.dk posts:

28. Jan 2010 AJAX and comet · Code · JavaScript · Plurk · Tips
© Amir Salihefendic