Tuesday, September 30, 2014

Don't What it, Hitch It

Async callbacks and closures is an incredible thing about JavaScript.   This is what makes environments like nodejs possible, a topic of many blogs to come.  Many of the JavaScript frameworks like my favorite framework Dojo have the ability to deal with closures and callbacks.  One of the issues that one needs to deal with is getting a handle to the current scope within a closure.

We discussed this and how to deal with it in Dojo in a previous blog.

http://dominointerface.blogspot.com/2014/03/when-is-this-is-this-and-what-is-this.html


The nice thing about Dojo is how extensive the library is.  This is also a negative thing since there is so many features that you might not beware of. As I am converting our iPhora library from Dojo 1.53 to Dojo 1.10.0, I realized there is also another method that you can use to get a handle to the current scope within a closure and that is dojo.hitch which has been around for a long time. 

In our previous example, we had a simple widget.

<div class="widget" id="happy">
<ul>
<li id="1">
  <a href="#" tabindex="-1"><i class="icon-tools"></i>Hello</a>
 </li>
<li id="2">
  <a href="#" tabindex="-1"><i class="icon-tools"></i>Hello</a>
 </li>
<li id="3">
  <a href="#" tabindex="-1"><i class="icon-tools"></i>Hello</a>
 </li>
<li id="4">
  <a href="#" tabindex="-1"><i class="icon-tools"></i>Hello</a>
 </li>
<li id="5">
  <a href="#" tabindex="-1"><i class="icon-tools"></i>Hello</a>
 </li>
</ul>
</div>

To get handle to this within the closure, you can use this method
dojo.query('ul > li',this.domNode).connect('onclick',this,function(e){
 alert(this.id);
});


or define "what" equal to "this" to get a handle
var what=this;
dojo.query('ul > li',this.domNode).connect('onclick',function(e){
 alert(what.id);
});


With Dojo, you can also provide the current scope "this" by using dojo.hitch
require(["dojo/_base/lang","dojo/query"],
  function(lang,query){
    query('ul > li',this.domNode).on('click',lang.hitch(this,function(e){
       alert(this.id);
      }));
});


Though you can use dojo.hitch in this way to replace the previous methods, one of the best ways to use dojo.hitch is with async xhr callbacks.  dojo.hitch provides an elegant approach when you need to do a callback during an async request.  I use this all the time for populating widgets or in the case of the MVC terminology, controllers.

If you try this.
require(["dojo/_base/xhr"], function(xhr){
  var args = {
    url: "hostnameurl",
    load: this.callback
  };
  xhr.get(args);
});


you will get an error because "this" is not defined within the closure of the xhr request. You could define var what=this provide a handle as we did before. However, dojo.hitch is a better solution.

require(["dojo/_base/xhr","dojo/_base/lang], function(xhr,lang){
  var args = {
    url: "hostnameurl",
    load: lang.hitch(this,callback)
  };
  xhr.get(args);
});

Now, you can get a handle to your current scope "this" and your callback will not bomb.

No comments: