Tag Archives: dojo

Use dojo’s promise.all in non-failure mode

The “all” function “Takes multiple promises and returns a new promise that is fulfilled when all promises have been resolved or one has been rejected.” This makes a lot of sense. If you are invoking multiple asynchronous services in parallel and want to wait for all of them before continuing with a “reactive” function, you probably want to not run this function if one of the services fails.

In some scenarios you do want all the service invocations to complete and then deal with the results whether success or failure. Thus, it would be nice to have a version of ‘all’ that did this.

The now deprecated DeferredList may have supported this. See this reference.

Some() function implementation
Below in listing one I created a function ‘some’ that transforms the input to ‘all’ to accomplish this. This simply takes each promise argument (in array or object) and chains an always(…) Thenable. This Thenable promise link takes a handler that will be invoked whether the prior promise is resolved or rejected. It acts like a ‘finally’ in a try .. catch .. finally.

A better approach would have been to create an alternative to the ‘all’ function that did this.

/**
 * Takes an object or array of promises and creates a new array of 
 * promises that do not fail.
 * <p>
 * The Dojo/All function is fulfilled when all promises 
 * have been resolved or when one has been rejected.
 * In certain scenarios even if some promies
 * @author J. Betancourt 
 * @since 2014/11/04
 * @param objectOrArray  Object|Array?
 * @returns {Array} of promises.
 */
;function some(objectOrArray) {
    "use strict";
    
    var promises = [];
    require([ "dojo/_base/array", "dojo/Deferred", 'dojo/when' ],
      function(array, Deferred, when) {
        var origPromises = [];
        if (objectOrArray instanceof Array) {
            origPromises = objectOrArray;
        } else {
            for ( var key in objectOrArray) {
                if (Object.hasOwnProperty.call(objectOrArray, key)) {
                    origPromises.push(objectOrArray[key]);
                }
            }
        }
        // create array with each item a promise chain.
        array.forEach(origPromises, function(item){
           promises.push(when(item).always(function(res){return res;}));
        });
    });
    
    return promises;  // array of dojo/promise/Promise
    
} // end some(objectOrArray) function

Listing 1

Example
Below in Listing 2, this function is used. Available on jsFiddler.

<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"  
    data-dojo-config="async:false"></script>
<script src="scripts/some.js"></script>

<script>
    require([ "dojo/Deferred", "dojo/promise/all",
	 "dojo/dom", "dojo/on","dojo/domReady!" ], 
        function(Deferred, all, dom, on) {
        "use strict";    
        
        function show(msg){
            dom.byId('output').innerHTML += msg + '<br/>';
        }
        
        /**
         * Use setTimeout to simulate an async process.
         * @param {string} name the name of this async invoke
         * @param {boolean} fail if true fail the promise
         * @returns {Promise} dojo/promies/Promise
         */
        function async(name, fail){
            var deferred = new Deferred();
            setTimeout(function(){
                if(fail){
                    deferred.reject(name + "Failed!");
                }else{
                    deferred.resolve(name);
                }
            },1000);
            
            return deferred.promise;
        }
        
        /**
         * On click of 'StartButton' button 
		 * wait for an array of promises. 
         */
        on(dom.byId("startButton"), "click", function() {
            var multiples = [async('V0'),
			 async('V1',true),async('V2')];
			 
            var p = all(some(multiples))
            .then(function(result){
                show(result);
                console.log(result);
            },
            function(err){
                // this should not be reached.
                show(err);
                console.log(err);
            });
        });
    });
</script>
</head>
<body>
    <button type="button" id="startButton">Start</button><p/>
    <div id="output" style="border: 1px black solid;width:20em;margin-bottom:20px;">Ready<br/></div>
</body>
</html>

Listing 2

Further reading

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

JavaScript Chaining Promises to Promises

When you create a Promise you can chain asynchronous behavior by using the then(success,fail) method. The success and fail are callback functions invoked appropriately when the promise is resolved or rejected. Note that since ‘then(…)’ returns a promise, this technique is called promise chaining: p.then(…).then(….).

What I discuss in this post are two subjects
1. How to ‘stitch’ multiple promises together?
2. How to ‘splice’ in a value into a promise chain?
3. How to chain using a promise object as an argument?

What if in complex application you already have promises objects and want to create promise chains linking them to each other? How would you do this with ‘then’ methods? Amazingly, in most examples of using Promises on the web this simple scenario is never presented directly. Granted it doesn’t *seem* to be relevant.

Here is the source of a simple demo based on one of the Dojo Deferred examples. It is ‘normal’ promise chaining. I’m using this as the basis for the investigation presented here. The output displayed on page should be: completed with value: 75

The actual chaining ‘stitching’ is setupTrans().then(function(x){return action()}).then(outputValue);

<!DOCTYPE html>
<html >
<head>

<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"  data-dojo-config="async:false"></script>
	
<script>
require(["dojo/when", "dojo/Deferred", "dojo/dom", "dojo/on", "dojo/domReady!"],function(when, Deferred, dom, on){
	  var balance = 100;

	  function asyncProcess(x){
	    var deferred = new Deferred();
	
	    setTimeout(function(){
	      if(x === 'plus' || x === 'minus'){
	      	 x === 'plus' ? (balance += 25) : (balance -= 25);
	      } 
	      deferred.resolve(balance);
	    }, 1000);
	
	    return deferred.promise;
	  }

	  function setupTrans(){
	  	return asyncProcess('z');
	  }

	  function debitAccount(){
		return asyncProcess('minus');
	  }
	
	  function creditAccount(){
		return asyncProcess('plus');
	  }

	  function outputValue(value){
	    dom.byId("output").innerHTML += "<br/>completed with value: " + value;
	  }
	  
	  on(dom.byId("startButton"), "click", function(){
	  	var debit = true;
	  	var action = debit ? debitAccount : creditAccount;
	  	
	  	setupTrans()
	  	.then(function(x){return action()})
	  	.then(outputValue);
	  	
	  });
});
</script>
</head>
<body class="claro">
    <h1>Output:</h1>
	<div id="output"></div><p />
	<button type="button" id="startButton">Start</button>
</body>
</html>

What is ugly is the inline function. Luckily I found the “Flattening Promise Chains” article where the author shows how to get rid of the function and simplify. However that article didn’t answer my question, how can you simply and directly chain promise objects. What the article showed is that you have to use the correct structure or design. Well, of course, but …


Answer
I thought this would be difficult. The Dojo documentation page never mentions that instead of the first ‘then’ argument being onFulfilled handler function it could be an actual promise object. But this is mentioned in specs such as the Promises/A+ specification. Or does it? The ‘Promise resolution procedure’ seems to mix compile time view with runtime, or I’m reading it incorrectly. Q documentation is very good on this. Will have to research further.

To directly chain separate promise chains the above code sample is modified as follows by just using an existing promise as the argument to another chains then(…) method. However, this can only be done using a promise returning function.

  on(dom.byId("startButton"), "click", function(){
  	var debit = true;
  	var action = debit ? debitAccount : creditAccount;
  	
  	setupTrans()
  	.then(action)
  	.then(outputValue);
  	
  });

Or, to inline the decision:

  on(dom.byId("startButton"), "click", function(){
  	var debit = true;
  	
  	setupTrans()
  	.then(debit ? debitAccount : creditAccount)
  	.then(outputValue);
  	
  });


Chaining using actual promise objects inside the then(f,r) is made easy using the approach shown next, using “scalars”.

Chaining values into promise chains
While looking at this subject I thought about a situation where we want to directly insert a known value into the chain so that the next ‘link’ will use this as the prior handler’s return value.

We have a chain, and I want to put the great Answer in there. This won’t work: var p1 = promiseReturningFunction().then(…).then(’42’).then(….).

Sure you can wrap ’42’ in an inline function then(function(){return ’42’}), but that is yucky. How about a function that does that:

     /** return a function that returns the value */
     function now(value){
    	  return function(){return value;};
      }

Now you can do: var p1 = async().then(…).then(now(’42’)).then(….);

Here is the prior source code with the changes. This is just some of the script changes. The output on screen is:

completed with value: 75
completed with value: Goodbye

      /* ...  */

      function outputValue(value){
        dom.byId("output").innerHTML += "<br/>completed with value: " + value;
      }
      
      function now(valueOrPromise){
    	  return function(){return when(value);};
      }
      
      on(dom.byId("startButton"), "click", function(){
        var debit = true;
        var action = debit ? debitAccount : creditAccount;
        
        var promise1 = setupTrans()
        .then(debit ? debitAccount : creditAccount)
        .then(outputValue)
        .then(function(){
        	console.log("now do another promise chain...");
        });
        
        promise1.then((now('Goodbye'))).then(outputValue);
        
      });


Using promise object directly in then(f,r) by using now(x)
With the Promises implementation in Dojo, you can’t use promiseObject.then(anotherPromiseObject). And you can’t use promiseObject.then(when(anotherPromiseObject)). At least, I haven’t figured how to do it.

With the now(x) function shown above, this is easy. The code below will output:

completed with value: 75
completed with value: 100
completed with value: undefined
completed with value: finished both chains

     /** return function that returns the value 
         or apply Dojo's when(...) to return a Promise 
      */
     function now(valueOrPromise){
    	  return function(){return when(value);};
      }
      
      on(dom.byId("startButton"), "click", function(){
        var debit = true;
        var action = debit ? debitAccount : creditAccount;
        
        var promise1 = setupTrans()
        .then(action)
        .then(outputValue)
        .then(function(){
        	console.log("now do another promise chain...");
        });
        
        debit = false;
        action = debit ? debitAccount : creditAccount;
        var promise2 = setupTrans()
        .then(action)
        .then(outputValue);
        
        promise1
        .then(now(promise2)).then(outputValue)
        .then(now("finished both chains"))
        .then(outputValue);
        
      });
});

Groovy language has Promises too
GPars brings Promises to the Groovy language.

Further reading

  1. Flattening Promise Chains
  2. A Deeper Dive Into JavaScript Promises
  3. How-to Compose Node.js Promises with Q
  4. Promise Anti-patterns
  5. dojo/when
  6. q
  7. General Promise Resources
  8. Promises/A+
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

JavaScript Promise example, reverse geocode location

In prior post we wrapped the Google Map API in a Promise. Now we wrap navigator.geolocation.getCurrentPosition in a similar promise. This allows us to to neatly chain these two to get the browser’s current address.

The example is using Dojo’s Promise implementation, but the approach is applicable to other Javascript Promise libraries or native support.

In listing 1 below I reproduce the former getGeocode function.

Listing 1, Get geocode using Google service

function geoCode(request) {
    var deferred;
    require([ 'dojo/Deferred' ], function(Deferred) {
        deferred = new Deferred();        
        new google.maps.Geocoder().geocode(request, 
          function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                deferred.resolve(results);
            } else {
                deferred.reject(status);
            }
        });
        
    });
    
    return deferred.promise;
    
}

In listing 2 below we have a similar function

Listing 2, get browser location.

function getLocation(){
    var deferred;
    require([ 'dojo/Deferred' ], function(Deferred) {
        deferred = new Deferred();
        navigator.geolocation.getCurrentPosition(
            function navSuccess(position){
                deferred.resolve(position);
            },function navFail(){
                deferred.reject(posError);
            }
        );
    });

    return deferred.promise;
}

Hmmm. The code is very similar. It seems that these two functions could be done using a Promise wrapper function, like toPromise(doFunction, onSuccess, onFailure). Is there such a beast?

Now we can use them together, as shown in listing 3. Here instead of a simple promise chaining we use the technique presented in “Break promise chain and call a function based on the step in the chain where it is broken (rejected)” to “catch” the correct error and not have it bubble up the ‘then’ chain.

Listing 3, get browser location, then reverse geocode

function findCurrentLocation(){
    var request;

    if (navigator.geolocation) {
        getNavLocation().then(
            function navSuccess(position){
                request = {
                    'location' : 
                      new google.maps.LatLng(
                        position.coords.latitude, 
                        position.coords.longitude)
                };

                return getGeoCode(request).
                   otherwise(function geoCodeError(status){
                     throw new Error(status);
                   }
                );
            }, function navFailed(err){
                console.log('navLocation() failed: " + err); 
                throw new Error(err);       
            })
            .then(function geoCodeSuccess(results){
                    console.log('navLocation() success: " + results);
                } 
            );
    }
}

Above, .otherwise(onFailure) is just a shortcut for .then(null, onFailure)

Of course, the code doesn’t have enough error handling and actual use of the data obtained.

Further reading

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

JavaScript focus event has wrong target?

I had an amusing debugging experience. Well, now it’s funny, then not so much. A focus event handler was getting events that said the same field was generating them. Even if other fields were selected.

I am using Dojo’s event API. This, like most other frameworks, make JavaScript event handling very simple, and most importantly handle the cross-browser issues.

The event tracer
I put a listener on a field’s ‘change‘ event using dojo/on, example:

on( theNode,'change',
      function(evt){
          mode = 'rent';			
      }
);

The callback handler just set a state variable. I also attached a listener to the ‘focusin’ event on a few other fields using the ‘on‘ method of Dojo’s NodeList:

query.NodeList().concat([moeNode,larryNode,curlyNode]).on('focusin',function(evt){
	evt.stopPropagation(); // needed?
	if(mode == 'rent'){
	    doSomeRentyThings(evt);
        }
});

This second handler used the value of the state variable. That is, I wanted to know that the user went from a particular field ‘A’ to another group of fields ‘B’. Hopefully someone can tell me the correct way to do something like this. Yes, a kludge, but it had to be done immediately, not on a single ‘submit’ button.

What should happen is that when the mouse leaves the first field (or user tabs away) and lands on one of the second fields, the status variable would have the correct value and be used by the second handler. It works!

Since the field setting is very fast, very few users could be faster. I know, async stuff; the browser could have a delay, etc. Don’t try this at home. Hmmm, but the browser is single threaded, so how could …. Anyway, in this app that would not be a disaster.

It stopped working
But, then I was developing something else on the same page using the Chrome debugger, and the above kludge stopped working. Huh? Even if I clicked on empty space in the browser, the event captured would be from the last field that the mouse was on. I re-read the Dojo docs, went back to the W3C stuff on Events, etc. Could find no web site where someone experienced a similar issue. I started blaming the Dojo toolkit, maybe there is a bug or the docs are incorrect.

I asked a co-worker, but they didn’t want to solve the problem just tell me that the app requirements were wrong, it’s too complex, blub, blub, blub. Most of the time feedback like this is important. One can get stuck in fruitless paths or need to see a different view of the goals. Perhaps, but in this case something obvious was wrong and I will probably face the same debug problem in the future.

Solution
Then I noticed that when I went from the Debugger back to the browser and clicked on another field, a very brief underline appeared in the previously selected field. Ah, how dumbskevisky, when I click on the browser anywhere, the previously selected field regains the focus and the focus event is generated. Obviously. The switch from debugger window to the browser window was the real change.

How did I confirm my observation? I closed the debugger window, and added console logging, like: console.log(“focus event on: ” + evt.currentTarget.name);

Take away

  1. Blame the tools last.
  2. Was working now not, what really changed?
  3. If it is hard to find a similar problem on web, your doing something wrong.
  4. When you ask co-workers for input be mindful of changing the context.
  5. Debuggers, while useful, can cause problems. The console is your friend.
  6. Take a break and work on something else.

What’s next?
There just has to be a better way of satisfying my web page requirements. No app at any point in time wanted to know what was previously changed?

Links

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.

dojo on.emit won’t work in FireFox?

Seems simple enough, using the Dojo toolkit click a div and trigger an anchor tag on the page.

The code in listing 1 below works on:
Chrome version 35
Internet Explorer 11

Won’t work on FireFox ver 30.

Dojo’s dojo/on module has the emit() method that provides a normalized way to dispatch events. It is supposed to be cross-browser.

From the info on this page, Disabling native events when using Firefox with WebDriver, it sounds like Dojo may, like WebDriver, be using FireFox’s native event facilities and failing.

<!DOCTYPE html>
<html >
<head>
    <script>dojoConfig = {async: true, parseOnLoad: false}</script>
    <script src="http://ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"></script>
    
    <style media="screen" type="text/css">
        .bold {font-weight: bold;}
        .box {border:1px black solid;margin-top:4em;margin-left:8em;}       
    </style> 
    
    <script>
        require(['dojo/ready','dojo/on','dojo/dom',
                   'dojo/query','dojo/domReady'],
        function(ready,on,dom,query){
            ready(function(){
                var nde = query('#div123');
                nde.on("click",function(evt){
                    on.emit(dom.byId('target'),"click",
                     {bubbles:false,cancelable:false});
                });                 
            });
        });             
    </script>       
    
</head>
<body class="claro">
    <div id="div123" class="bold box">click me!</div>
    <div class="box">
     <a id="target" href="javascript:alert('hello')">will trigger this link</a>
    </div>
</body>
</html>

Listing 1

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.