html5 communication,Methods of communication

By now, you’ve surely realised that “HTML5” is so much more than just markup. There’s also an army of associated JavaScript APIs. Among the ranks are a few new technologies that open up how we communicate between client and server and across documents. Let’s take a look.

This post will be an overview of the technologies available, how well they’re currently supported, and, where possible, live demos. I’m going to touch on the following technologies:

XHR & XHR2 with CORS

Web Messaging

Web Sockets

Server Sent Events

Web Workers

Before I get on to the APIs, I want to outline a fairly common communication model that several of these APIs use.

A common communication event model

All event handlers (with the exception of XHR) receive an event object containing a data property. This property includes the data sent as part of the message.

The event model (again with the exception of XHR) is mostly based around onmessage and postMessage or send. For example:

// in the recipient code

recipient.onmessage = function (event) {

console.log('received message: ' + event.data);

};

// from the sender code

recipient.postMessage('hi there'); // or recipient.send('hi there');

This is just a common model and isn’t the exactly the same among all these technologies. The two key similarities are that they use:

a sending method (postMessage or send) on the recipient object, and

an event handler that listens for the message event and receives an event object containing a data property.

Very importantly, most browsers only support sending strings from sender to recipient, so we often need to JSON stringify and parse if we want to send anything other than a string.

XHR & XHR2 with CORS

XHR can be both synchronous and asynchronous. XHR is the only API that (purposely) supports synchronous requests, meaning the execution of code will block until the callback fires.

There’s nothing particularly new about XHR, but in XHR2 we can handle uploads, and there’s a progress event to tell you how the upload or download is getting on.

The super shiny new toy in XHR2 is its support for Cross-Origin Resource Sharing (CORS). This means you can make an XHR request across domains, but only if the server you’re connecting to allows it.

The request is as you’d expect from XHR:

var client = new XMLHttpRequest();

client.onreadystatechange = function () {

if (this.readyState == 4 && this.status == 200) {

alert('The most awesome-est person to follow: ' + this.responseText);

}

};

client.open('GET', '/no-cors');

client.send();

If our server responds with a CORS header, however, we can put our XHR responder on another server. So on the URL http://remysharp.com/demo/cors.php, I have the following PHP script:

header('Access-Control-Allow-Origin: *');

?>

@rem

This says that anyone can make an XHR request to this particular script. Now when I run the following code in a browser that supports XHR2, the cross domain request succeeds!var client = new XMLHttpRequest();

client.onreadystatechange = function () {

if (this.readyState == 4 && this.status == 200) {

alert('The most awesome-est person to follow: ' + this.responseText);

}

};

client.open('GET', 'http://remysharp.com/demo/cors.php');

client.send();

Note that IE8 supports CORS, but not XHR2 (no surprise there then). You need to use their proprietary (booo!) XDomainRequest object. Nicholas C. Zakas has an excellent article explaining how to handle these differences.

XHR usage is pretty common already, but XHR2 with CORS is a winner over JSON-P, particularly as you have finer control over the request, can handle timeouts, and can handle errors correctly.

Support for XHR & XHR2 with CORS

XHR support is pretty solid nowadays (even though IE6 uses ActiveXObject to get it going)

XHR2 with CORS: Safari & MobileSafari, Firefox 3.5, Chrome and IE8 (via XDomainRequest)

postMessage

This API is older, but it’s very useful if you want to get around the XHR same-origin rules. If you have an document that can accept onmessage events from your origin (i.e., your site), then you can communicate across domains (and origins).

For example, a page that accepts an onmessage event might contain code such as this:

window.onmessage = function (event) {

if (event.origin == 'mytrustedsite.com') {

alert('my trusted site said: ' + event.data);

}

};

Now you can include an that contains that code, and using the DOM node, you can post to the :

// where iframe is the actual iframe DOM node

iframe.contentWindow.postMessage("hello there", location.host);

This gives you the ability to send strings across two mutually trusted domains. (Remember that you can use JSON.stringify and JSON.parse to convert to an object to and from string format.)

Support for postMessage

Chrome

Safari

Opera

Firefox

IE8

There’s also a project called EasyXDM, which adds cross domain messaging to IE6 and upwards (along with all the other browsers) through the library’s abstraction. Definitely worth a look if this is a route you need to take.

Web Sockets

It’s my opinion that Web Sockets replaces Comet. Comet is a way of hacking the browser to giving us real-time server messages. The Web Sockets API provides that natively.

Web Sockets are used to send messages to and from the server — i.e., a bi-directional socket. In contrast to other similar technologies, with Web Sockets, you can go across domains, and you’re not bound by the same-origin policy. This means you can host your normal “apps” server while another server is for streaming content. Or you could host your own pages and connect to a live Twitter stream if your users turn on Web Socket support.

You can only send messages once the socket is open (duh). The communication model looks like this:

var ws = new WebSocket('ws://somesite.com/updates');

ws.onmessage = function (event) {

alert(event.data);

};

ws.onopen = function () {

ws.send('yay! we connected!');

};

Once the socket is closed, you can’t reuse it. Similarly, there’s no explicit method for opening a socket. That just happens when you create the WebSocket object.

This API is extremely simple. I most often get asked, “What do you put on the server side?” I personally use Node, but you could use an Nginx server or something like Jetty. I’m no expert on the latter servers, but I can vouch that a Node-based server is very, very simple to get going. The live demo below also includes a link to the code that I used to run the server.

Support for Web Sockets

Chrome

Safari & MobileSafari

There’s also an excellent Flash poly-fill called web-socket-js. Drop this into an application and it provides Web Sockets support as if it were native. I’ve used this on a few projects of my own, and it works very well.

In early December 2010, there was a security notice posted about Web Sockets, and both Firefox and Opera pulled it from their upcoming releases. Mozilla have said that they expect Web Sockets to be back in Firefox by version 4.0.1.

Server-Sent Events

The Server-Sent Events API is something that originated from Opera back in 2006 and is used for pushing events from the server to the client. Note that the client cannot send messages to the server through an EventSource (SSE) — it can only listen for messages.

This API uses the onmessage model. It’s constructed using the EventSource object and is limited by the same origin rules:

var es = new EventSource('/sse');

es.onopen = function () {

console.log('opened stream');

};

es.onmessage = function (event) {

console.log('new message: ' + event.data);

};

The SSE automatically connects when you create the object (similar to Web Sockets), and once open will trigger the onopen event.

Here’s how this is to work: when a new message is pushed from the server to the client, it triggers the onmessage callback.

The key to your server is ensuring it doesn't close the connection on the client - the browser. Most of the examples around the web are doing this: closing the connection which tells the API to switch in to polling mode (note that this is the exact problem I hit when I first published this article).

When the API is in polling mode, it's no more different from an XHR poll, and the onopen will continually fire.

Al the code the server side can be viewed here: custom-echo.js (note that it's running on a Node.js server). There's a bit more code than you'd expect, because it's doing a few things:

1. Handling HTTP requests for files (and therefore is able to serve itself)

2. Handling the server-sent events and not closing the connection

3. Setting up a Web Socket server, and when a new connection comes in, it sends a server-sent event to all the currently connected sessions.

Support for Server-Sent Events

Opera 11

Safari & MobileSafari

Chrome

Web Workers

Web Workers are a way of creating a new thread of execution inside the browser. I’m including this because you still need to communicate with your Web Workers, and the method of communication is similar to some of those techniques discussed above. Do note, however, that this is not a method communicating from a client (browser) to a server. It’s more like there’s another browser window executing a particular block of JavaScript.

As an example of when to use a Web Worker, say you’re running a lot of JavaScript and the UI becomes unresponsive. The browser UI hangs because, in a way, it’s a “single-threaded application”. (Under the hood it isn’t really, but from a rendering and JavaScript perspective it is). This JavaScript task could be given to a Web Worker so that the UI can continue functioning.

It’s vital to understand that a Web Worker lives in a sand-boxed environment that doesn’t have access to things like the DOM. What’s more, you can only communicate with it using the onmessage and postMessage functions.

Our application can create and send messages to a worker using the following code:

var worker = new Worker('bigjob.js');

worker.onmessage = function (event) {

alert('Message from worker: ' + event.data); // remember event.data is a string!

};

worker.postMessage('task=job1');

In the JavaScript file bigjob.js, we run some computationally intensive task and listen for messages in a way similar to what we’ve done in the previous examples. We can also post messages back to the invoking application:

this.onmessage = function (event) {

var job = event.data;

if (job == 'task=job1') {

job1();

} else if (job == 'task=job2') {

job2();

}

};

// just a pseudo example

function job1() {

// do some big task

while (working) {

// continue task

this.postMessage('job1 ' + amountComplete + '% complete');

}

this.postMessage('job1 100% complete');

}

There’s a lot more to Web Workers than just running a couple of small tasks, and no doubt we HTML5 Doctors will be posting a detailed article soon. This example just demonstrates how to communicate with Web Workers and how similar that is to the other technologies we’ve discussed here.

Support for Web Workers

Chrome

Safari

Opera

Firefox

A final word

Hopefully you agree that this is just the tip of the iceberg of communicating between client and server in HTML5. We’re no longer stuck with the same origin policy we had with vanilla Ajax. In fact, when you think about it, since IE8, we’ve actually had decent cross-domain messaging.

I’m personally most excited about Web Sockets and the support of CORS in services that have APIs, like Flickr, Twitter, and URL shorteners. What could you build with this?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值