{"id":2434,"date":"2015-02-19T13:15:07","date_gmt":"2015-02-19T11:15:07","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=2434"},"modified":"2015-02-16T00:23:14","modified_gmt":"2015-02-15T22:23:14","slug":"real-time-communication-angularjs-qorlate","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/","title":{"rendered":"Real-time Communication in AngularJS with ($Q)orlate"},"content":{"rendered":"<p>This post introduces the lightweight <a href=\"https:\/\/github.com\/jeremylikness\/qorlate\" target=\"_blank\">($Q)orlate<\/a> library.<\/p>\n<p>A popular type of engagement that <a href=\"http:\/\/www.ivision.com\/\" target=\"_blank\">iVision<\/a> is hired for is the architecture assessment. For assessment projects we analyze the existing system, weigh our own experience, industry standards and best practices against what we find, then provide feedback and a potential road map to iterate towards a desired solution.<\/p>\n<p>I\u2019ve participated in everything from an over-arching analysis of the entire technology stack with associates from our data center, converged networking, and infrastructure practices to provide a business\/IT roadmap for cloud readiness to a very targeted analysis of AngularJS implementations.<\/p>\n<p>Recently I worked with a customer that built a very mature proof-of-concept using Angular in a system that had what I call \u201cdisconnected asynchronous processes.\u201d These are processes that are truly \u201cfire and sort of forget\u201d because the message goes through message queues and workflows prior to a response being generated through a different channel. Although my first step is always to challenge this type of architecture (sometimes it\u2019s implemented with the belief it is automatically faster or more scalable when there are other approaches that can achieve the same results with less complexity), in this case it truly seemed like the right architecture needed by that system.<\/p>\n<p>I am constantly looking for opportunities to simplify and\/or refactor code to reuse common components, algorithms, and strategies. This makes it easier to maintain and understand the code and provides developers with a toolbox to use so they can plug in the repeatable pattern and focus on what is unique about their part of the application. This led to me brainstorming what I\u2019ve seen in these types of systems with Angular and I came up with three very distinct scenarios that I felt could be addressed with a lightweight Angular service.<\/p>\n<h2>1. Cached Requests<\/h2>\n<p>Angular has its own built-in mechanisms for controlling a cache. It is a common pattern for a service to asynchronously request information that is used by other components. Sometimes your app may get caught in a chicken-egg scenario when a component relies on a central service for information but must wait for that information to appear. For example, it may be necessary to retrieve security information from the server prior to building a menu or servicing requests.<\/p>\n<p>There are a few ways to deal with this in Angular. One is to create the promise on the route, which will delay loading a view until the promise is satisfied. This isn\u2019t an option if you aren\u2019t using routes and sometimes your services may not be specific to a route. Another mechanism is simply to return a common <a href=\"https:\/\/docs.angularjs.org\/api\/ng\/service\/$q#the-promise-api\" target=\"_blank\">promise<\/a>. Multiple callbacks can be registered, so if the service keeps track of a single promise it can keep providing it, and even if it was resolved in the past the promise will be satisfied.<\/p>\n<p>To see what I mean, take a look at <a href=\"http:\/\/jsfiddle.net\/jeremylikness\/1z2cuvpq\/\" target=\"_blank\">this jsfiddle<\/a>. Notice the second call happens long after the list was already populated, but the promise still fires and populates the second list (the list is populated after 1 second, and the second promise is requested after 2 seconds). The same promise is always returned.<\/p>\n<p>The following figure shows this scenario (you can assume the server simply calls out to the database, the queue and handlers will make more sense for the other scenarios).<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/02\/cachedrequests_thumb2.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2443\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/02\/cachedrequests_thumb2.png\" alt=\"cachedrequests_thumb[2]\" width=\"573\" height=\"448\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/02\/cachedrequests_thumb2.png 573w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/02\/cachedrequests_thumb2-300x235.png 300w\" sizes=\"(max-width: 573px) 100vw, 573px\" \/><\/a><\/p>\n<p>To enhance this scenario, ($Q)orlate provides an option to track multiple requests with timeouts. If timeout isn\u2019t a concern or is handled locally, the straightforward use of <a href=\"https:\/\/docs.angularjs.org\/api\/ng\/service\/$q\" target=\"_blank\">$q<\/a> will suffice. What ($Q)orlate does is provide a mechanism to automatically timeout and expire the request, so it keeps track of multiple requests even if you satisfy them with a single call.<\/p>\n<p>The call to ($Q)orlate is passed an id that uniquely identifies the correlation (it will generate one for you if you do not pass one in). In <a href=\"http:\/\/jeremylikness.github.io\/qorlate\/sample\/deferred-initialization-timeout.html\" target=\"_blank\">this example<\/a> a timeout is used to emulate the delayed response. Notice the resolution has an extra parameter for the correlation.<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\n$timeout(function () { \r\n\t_this.list = &#x5B;1, 2, 3, 4, 5];\r\n\t_this.qorlate.resolve(_this.id, _this.list);\r\n\t}, qorlate.defaultTimeout + 100\r\n);\r\n<\/pre>\n<p>The service always returns a correlation. This is because qorlate will immediately return the last promise that was resolved or rejected, so any values (success or error) will be satisfied in the promise.<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">return this.qorlate({ id: this.id }).promise;<\/pre>\n<p>The consumers simply call the service with a standard promise, and it will either be satisfied once the data is loaded or rejected when it times out (in <a href=\"https:\/\/github.com\/jeremylikness\/qorlate\/blob\/master\/sample\/deferred-initialization-timeout.html#L53-68\" target=\"_blank\">the example<\/a>, the initial call times out but the subsequent call works because the data has been loaded). ($Q)orlate guarantees the promise, so even if a request is rejected from a timeout and the original call returns, later requests will be resolved immediately with the result.<\/p>\n<p>Although this is one use case, ($Q)orlate is more suited to two other scenarios.<\/p>\n<h2>2. Discrete Disconnected Messages<\/h2>\n<p>I am purposefully using the label \u201cdisconnected\u201d instead of \u201casynchronous\u201d because a direct AJAX call can be asynchronous while it is still \u201cconnected\u201d in the sense there is a clear path from the call to the resolution of the promise. What is less clear is when the message is sent to be processed, then returns through another channel such as a websocket. The top section of the following figure demonstrates this:<\/p>\n<p><a href=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/02\/CorrelatedRequests_thumb1.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2444\" src=\"http:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/02\/CorrelatedRequests_thumb1.png\" alt=\"CorrelatedRequests_thumb[1]\" width=\"574\" height=\"417\" srcset=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/02\/CorrelatedRequests_thumb1.png 574w, https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2015\/02\/CorrelatedRequests_thumb1-300x218.png 300w\" sizes=\"(max-width: 574px) 100vw, 574px\" \/><\/a><\/p>\n<p>I call this a correlated event because even though the return event is surfaced independently of the request (i.e. via a Web Sockets connection), it is correlated to the initial request. For example, you might have a form that submits to a queuing system, is validated by a handler on the backend, then the response is routed back. In these cases, you still want to keep track of the message (i.e. if it times out it is probably good to inform the user) but the API might not be so clear. Consider something like this that you may be used to:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nvar id = 1;\r\nfunction sendRequest() {\r\n\tservice.on('response', function (response) {\r\n\t\tif (response.id === id) {\r\n\t\t\t\/\/ do something\r\n\t\t\t\/\/ and don't forget to unregister\r\n\t\t}\r\n\t} service.send(id, request);\r\n}\r\n<\/pre>\n<p>Basically you must keep track of your correlation and register to listen to all returned events, parse out the one you are interested in, then remember to unregister from the event (or just let it fire assuming the identifier won\u2019t repeat), then finally fire off your message.<\/p>\n<p>One of the nice things about the promise specification is that it helps make code cleaner and easier to read. What if you could do something like this instead:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nservice.request(id, request).then(\r\n\tfunction success(response) {\r\n\t\t\/\/ yes!\r\n\t},\r\n\tfunction error(err) {\r\n\t\t\/\/ nope!\r\n\t}\r\n);\r\n<\/pre>\n<p>This is a straight promise. Is that possible, even when the mechanisms are disconnected? The answer is, \u201cYes.\u201d The service simply needs to establish the promise with a correlation:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nvar correlation = this.qorlate();\r\nreturn correlation.promise;\r\n<\/pre>\n<p>When the message comes in, the correlation is notified:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">this.qorlate.resolve(correlation.id, response);<\/pre>\n<p>You can also reject the correlation, and the configurable timeout will also reject it automatically if the return message is not received within the timeout period. In the above example, the service generated the identifier. If you have GUIDs or other ways of matching messages, you can specify them when you generate the correlation and match it back. See a working example that demonstrates successful, failed, and timed out correlations <a href=\"http:\/\/jeremylikness.github.io\/qorlate\/sample\/custom-correlation.html\" target=\"_blank\">here<\/a> and view the source <a href=\"https:\/\/github.com\/JeremyLikness\/qorlate\/blob\/master\/sample\/custom-correlation.html\" target=\"_blank\">here<\/a>.<\/p>\n<p>If you look back at the second figure you\u2019ll see there is another section near the bottom that indicates alerts raised by the server completely independent of the client. These are \u201cbroadcast\u201d messages. You can certainly use mechanisms built into scope, but if you want a way that doesn\u2019t rely on scope, still participates in digest loops (so no matter the mechanism for notification, you are always guaranteed to notify your subscribers in the context of a digest loop), and is testable, consider the next scenario.<\/p>\n<h3>3. Event Aggregator or Pub\/Sub<\/h3>\n<p>The idea behind an event aggregator is straightforward. A central service \u201cbrokers\u201d messages. You simply post your message to the service, any component interested subscribes, then the message is broadcast to the subscribers.<\/p>\n<p>The subscription looks like this:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">\r\nvar cancel = q({subscribe:'addItem'}).always(function (item) { rs.list.push(item); });\r\n<\/pre>\n<p>In this case, the subscriber is responding any time the message is sent. An error\/rejection method may also be added so if there is a problem with the transport it will notify subscribers. I do realize <em>always<\/em> is used in a different context relative to promises, but it made sense here because that\u2019s what is happening \u2013 the message is always notifying the subscriber.<\/p>\n<p>The call to ($Q)orlate will return a function to cancel the subscription \u2013 that\u2019s as easy as calling cancel(); and you\u2019re unsubscribed. The API to raise an event is no different:<\/p>\n<pre class=\"brush: php; title: ; notranslate\" title=\"\">q.resolve('addItem', (new Date()).getTime());<\/pre>\n<p>In fact, as you can see from the <a href=\"http:\/\/jeremylikness.github.io\/qorlate\/sample\/tests.html\" target=\"_blank\">test specifications<\/a>, you can overload the same identifier with promises <em>and<\/em> subscriptions. The module is fairly lightweight. It:<\/p>\n<ul>\n<li>Creates a promise when the function is called<\/li>\n<li>Sets a timer to reject the promise if the timeout is hit (this is configurable at the provider level and the individual call)<\/li>\n<li>Tracks the promises so when the correlation is resolved or rejected it can notify all consumers<\/li>\n<li>Generates a fresh set of promises for recurring subscriptions<\/li>\n<\/ul>\n<p>Because it is all based on the underlying $q service, you do not have to worry about a return call being generated outside of a digest loop as $q is integrated with the root scope.<\/p>\n<p>You can browse the source, offer feedback, generate pull requests, read the full documentation, run the tests and read the samples online at <a href=\"https:\/\/github.com\/jeremylikness\/qorlate\">https:\/\/github.com\/jeremylikness\/qorlate<\/a>. Enjoy!<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/csharperimage.jeremylikness.com\/2015\/01\/real-time-communication-in-angularjs.html\">Real-time Communication in AngularJS with ($Q)orlate<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/wcg\/\">WCG partner<\/a> Jeremy Likness at the <a href=\"http:\/\/csharperimage.jeremylikness.com\/\">C#er : IMage<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>This post introduces the lightweight ($Q)orlate library. A popular type of engagement that iVision is hired for is the architecture assessment. For assessment projects we analyze the existing system, weigh our own experience, industry standards and best practices against what we find, then provide feedback and a potential road map to iterate towards a desired &hellip;<\/p>\n","protected":false},"author":40,"featured_media":909,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25],"tags":[],"class_list":["post-2434","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular-js"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Real-time Communication in AngularJS with ($Q)orlate - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"This post introduces the lightweight ($Q)orlate library. A popular type of engagement that iVision is hired for is the architecture assessment. For\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Real-time Communication in AngularJS with ($Q)orlate - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"This post introduces the lightweight ($Q)orlate library. A popular type of engagement that iVision is hired for is the architecture assessment. For\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-02-19T11:15:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jeremy Likness\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/jeremylikness\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeremy Likness\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/\"},\"author\":{\"name\":\"Jeremy Likness\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/2cd31c082e3e1cc5f595ba18a6e03a43\"},\"headline\":\"Real-time Communication in AngularJS with ($Q)orlate\",\"datePublished\":\"2015-02-19T11:15:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/\"},\"wordCount\":1668,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"articleSection\":[\"Angular.js\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/\",\"name\":\"Real-time Communication in AngularJS with ($Q)orlate - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"datePublished\":\"2015-02-19T11:15:07+00:00\",\"description\":\"This post introduces the lightweight ($Q)orlate library. A popular type of engagement that iVision is hired for is the architecture assessment. For\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JavaScript\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Angular.js\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/angular-js\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Real-time Communication in AngularJS with ($Q)orlate\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/2cd31c082e3e1cc5f595ba18a6e03a43\",\"name\":\"Jeremy Likness\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b4d8ee78925818e3f7a4d0d82df06d34a2b76aa4d260a1f4b67dc0553efbf1b6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b4d8ee78925818e3f7a4d0d82df06d34a2b76aa4d260a1f4b67dc0553efbf1b6?s=96&d=mm&r=g\",\"caption\":\"Jeremy Likness\"},\"description\":\"Jeremy Likness is a principal architect at iVision, Inc. He has been building enterprise applications using the Microsoft stack for 20 years with a focus on web-based solutions for the past 15. A prolific author and speaker, Jeremy's mission is to empower developers to create success in their careers through learning and growth.\",\"sameAs\":[\"http:\/\/csharperimage.jeremylikness.com\/\",\"http:\/\/linkedin.com\/in\/jeremylikness\",\"https:\/\/x.com\/https:\/\/twitter.com\/jeremylikness\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/jeremy-likness\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Real-time Communication in AngularJS with ($Q)orlate - Web Code Geeks - 2026","description":"This post introduces the lightweight ($Q)orlate library. A popular type of engagement that iVision is hired for is the architecture assessment. For","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/","og_locale":"en_US","og_type":"article","og_title":"Real-time Communication in AngularJS with ($Q)orlate - Web Code Geeks - 2026","og_description":"This post introduces the lightweight ($Q)orlate library. A popular type of engagement that iVision is hired for is the architecture assessment. For","og_url":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2015-02-19T11:15:07+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","type":"image\/jpeg"}],"author":"Jeremy Likness","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/jeremylikness","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Jeremy Likness","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/"},"author":{"name":"Jeremy Likness","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/2cd31c082e3e1cc5f595ba18a6e03a43"},"headline":"Real-time Communication in AngularJS with ($Q)orlate","datePublished":"2015-02-19T11:15:07+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/"},"wordCount":1668,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","articleSection":["Angular.js"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/","url":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/","name":"Real-time Communication in AngularJS with ($Q)orlate - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","datePublished":"2015-02-19T11:15:07+00:00","description":"This post introduces the lightweight ($Q)orlate library. A popular type of engagement that iVision is hired for is the architecture assessment. For","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/real-time-communication-angularjs-qorlate\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"JavaScript","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/"},{"@type":"ListItem","position":3,"name":"Angular.js","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/angular-js\/"},{"@type":"ListItem","position":4,"name":"Real-time Communication in AngularJS with ($Q)orlate"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/2cd31c082e3e1cc5f595ba18a6e03a43","name":"Jeremy Likness","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b4d8ee78925818e3f7a4d0d82df06d34a2b76aa4d260a1f4b67dc0553efbf1b6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b4d8ee78925818e3f7a4d0d82df06d34a2b76aa4d260a1f4b67dc0553efbf1b6?s=96&d=mm&r=g","caption":"Jeremy Likness"},"description":"Jeremy Likness is a principal architect at iVision, Inc. He has been building enterprise applications using the Microsoft stack for 20 years with a focus on web-based solutions for the past 15. A prolific author and speaker, Jeremy's mission is to empower developers to create success in their careers through learning and growth.","sameAs":["http:\/\/csharperimage.jeremylikness.com\/","http:\/\/linkedin.com\/in\/jeremylikness","https:\/\/x.com\/https:\/\/twitter.com\/jeremylikness"],"url":"https:\/\/www.webcodegeeks.com\/author\/jeremy-likness\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/2434","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/40"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=2434"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/2434\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/909"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=2434"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=2434"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=2434"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}