diff --git a/content/tutorials/webmessaging/messagechannel/overview/en/index.html b/content/tutorials/webmessaging/messagechannel/overview/en/index.html new file mode 100644 index 000000000..c07cc91e0 --- /dev/null +++ b/content/tutorials/webmessaging/messagechannel/overview/en/index.html @@ -0,0 +1,232 @@ +{% extends "tutorial.html" %} + +{% block headauthor %}Raju Konga {% endblock %} + +{% block pagebreadcrumb %}Javascript Threads Communication{% endblock %} + +{% block head %} + +{% endblock %} + +{% block html5badge %} +This article is powered by HTML5 Performance & Integration +{% endblock %} + +{% block iscompatible %} + return !!window.MessageChannel; +{% endblock %} + +{% block content %} +

Introduction to Javascript Threads Communication

+

What are threads in Javascript? thread in javascript can be document main execution thread or it can be a webworker. These independant scripts can perform their jobs with no interaction between them, some cases needs interaction between them like two threads initailized in same document they need to share task.

+ +

How would communication between javascript threads can heppen? Web Messaging, it brings the cross document communication and channel messaging. This article will only covers channel messaging i.e; Message Channel.

+ +

Introduction to Channel Messaging

+

Channel messaging enables communication between two independent pieces of code. MessageChannel API gives you a way to implement channel messaging, MessageChannel API is a part of Web Messaging specification .Message Channel allows to communicate two independent scripts they can be documents from different origins, they can be two webworkers, individual unrealated scripts, etc... It helps to transfer messages to the other end without any media, both the threads can communicate directly via ports. Array of ports can be sent using ports property of event.Message Channel API + +

Message Channel API deals with three things MessageChannel constructor, Message Ports and Message Event. MessageChannel constructor creates new MessageChannel Object with two properties called port1 and port2 on each instance, each property of MessageChannel object is an instance MessagePort related to other property.

. + +

Ports can + send messages using postMessage API and + receives messages using onmessage event. + + start() enables the messaging on the port and + close() will terminates. +

+ +
+ Message Channel Flow Diagram +
Message Channel Flow
+
+ +

Getting Started

+

Detecting the MessageChannel support

+
+if(window.MessageChannel && window.MessagePort){
+	//Yes, you can use channel messaging
+}
+
+ +

Initializing a MessageChannel

+
+var msgChannel = new MessageChannel();
+//It returns MessageChannel object
+//MessageChannel {}
+//	|-port1: MessagePort
+//	|-port2: MessagePort
+
+ +

Passing the ports to scripts using postMessage

+
+window.postMessage(data,origin,[msgChannel.port2]);
+//postMessage can transfer the transferable objects with the message.
+//for webworkers ignore the origin parameter
+//worker.postMessage(data,[msgChannel.port2]);
+
+ +

Initializing the communication and listening to other port

+
+function portMsgListener(msgEvent){
+	//msgEvent is MessageEvent object
+	//msgEvent.data gives the data sent from other port
+	alert(msgEvent.data);
+}
+
+msgChannel.port1.addEventListener("message", portMsgListener, false);
+
+//start listening to messages from other port of message channel
+msgChannel.port1.start();
+
+ +

Receiving the port and storing for future communication purpose

+
+//otherWindow can be second worker or frame
+var otherEndMsgPort = null;
+function messageHandler(msgEvent){
+	if( messageEvent.ports.length > 0 ){
+		otherEndMsgPort = messageEvent.ports[0];
+		//It can be use for sending message to the other end
+		//otherEndMsgPort.postMessage(msg);
+		//otherEnd will receive msg
+	}
+}
+
+otherWindow.onmessage = messageHandler;
+
+ +

The messages sending through the ports are copies, not shared. Messages will get serialized and passed to the other port, they will get de-serialized on the other end. So the ports do not share same object instance, the copy of message receives on either port.

+ +

Great explanation on Transferable objects can be found here

+ +

Use Cases

+

The two different interesting use cases mentioned her, there can be many depending on different scenarios.

+
    +
  1. A document contains two frames with different origins, they need communication between them.
  2. +
  3. A game application initialized two workers and they need to share a job between them based on requirement.
  4. +
+ +

Example: Communication between web workers

+ +

One of the above mentioned use case explaining here.

+

In main thred:

+
+function msgChannelSetup(){
+	if(!supportsMessageChannel()){
+		//Don't have message channel support quit!
+		alert("Your Browser does not support Channel Messaging!");
+		return false;
+	}
+
+    var msgChannel = new MessageChannel();
+    var worker1 = new Worker("worker1.js");
+    var worker2 = new Worker("worker2.js");
+
+    // Setup the connection: Port 1 is for worker 1
+    worker1.postMessage({
+        command : "connect",
+    },[ msgChannel.port1 ]);
+
+    // Setup the connection: Port 2 is for worker 2
+    worker2.postMessage({
+        command : "connect",
+    },[ msgChannel.port2 ]);
+
+    worker1.postMessage({
+        command: "forward",
+        message: "this message is forwarded to worker 2"
+    });
+}
+
+function supportsMessageChannel(){
+	return window.MessageChannel && window.MessagePort;
+}
+
+ +

In worker1.js

+ +
+var worker2port;
+var onMessageFromWorker2 = function( event ){
+    console.log("Worker 1 received a message from worker 2: " + event.data);
+
+    //To send something back to worker 2
+    //worker2port.postMessage("");
+};
+
+self.onmessage = function( event ) {
+    switch( event.data.command )
+    {
+        // Setup connection to worker 2
+        case "connect":
+            worker2port = event.ports[0];
+            worker2port.onmessage = onMessageFromWorker2;
+            break;
+
+        // Forward messages to worker 2
+        case "forward":
+            // Forward messages to worker 2
+            worker2port.postMessage( event.data.message );
+            break;
+
+        //handle other messages from main
+        default:
+            console.log( event.data );
+    }
+};
+
+ +

In worker2.js

+ +
+var worker1port;
+var onMessageFromWorker1 = function( event ){
+    console.log("Worker 2 received a message from worker 1: " + event.data);
+
+    //To send something back to worker 1
+    //worker1port.postMessage("");
+};
+
+    self.onmessage = function( event ) {
+    switch( event.data.command )
+    {
+        // Setup connection to worker 1
+        case "connect":
+            worker1port = event.ports[0];
+            worker1port.onmessage = onMessageFromWorker1;
+            break;
+
+        // Forward messages to worker 1
+        case "forward":
+            // Forward messages to worker 1
+            worker1port.postMessage( event.data.message );
+            break;
+
+        //handle other messages from main
+        default:
+            console.log( event.data );
+    }
+};
+
+ +

Demo

+ +

The above example shows, how to forward message channel port to workers, how to handle other worker messages and main thread messages and communication between the workers

+ +

If there is no support in platform polyfill gives the support to use it. caniuse helps to the support.

+ +

References

+ + +{% endblock %} \ No newline at end of file diff --git a/database/profiles.yaml b/database/profiles.yaml index 19f93db3a..ee29ce474 100644 --- a/database/profiles.yaml +++ b/database/profiles.yaml @@ -1296,6 +1296,26 @@ email: developers@unit9.com --- +id: kongaraju +name: + given: Raju + family: Konga +org: + name: GE Digital + unit: Senior Staff Software Engineer +address: + locality: Bangalore + region: Karnataka + country: India + lat: 12.9667 + lon: 77.5667 +homepage: http://kongaraju.in +google: 115310382888220784299 +twitter: kongaraju +email: kongaraju@gmail.com + +--- + id: coltmcanlis name: given: Colt diff --git a/database/tutorials.yaml b/database/tutorials.yaml index ad89b3caf..cc5b6452c 100644 --- a/database/tutorials.yaml +++ b/database/tutorials.yaml @@ -1,3 +1,24 @@ +title: "Javascript Thread Communication" +url: /tutorials/webmessaging/messagechannel/overview/ +author_id: kongaraju +publication_date: 2022-02-22 +description: "The tutorial briefs communication between two contexts using channel messaging." +browser_support: +- chrome +- safari +- ff +- ie +- opera +tags: +- webmessaging +- messagechannel +- workers +- type:article +- class:performance +- class:nuts_and_bolts + +--- + title: "DevTools Digest - Chrome 35" subtitle: "Updates to the Developer Tools in Chrome 35" url: /tutorials/developertools/chrome-35/ diff --git a/static/images/profiles/kongaraju.jpg b/static/images/profiles/kongaraju.jpg new file mode 100644 index 000000000..cead47e68 Binary files /dev/null and b/static/images/profiles/kongaraju.jpg differ diff --git a/static/images/tutorials/message-channel-flow.png b/static/images/tutorials/message-channel-flow.png new file mode 100644 index 000000000..b2e849c71 Binary files /dev/null and b/static/images/tutorials/message-channel-flow.png differ