Thinking with JS Promise and Promises
/
Here's a real life example of a quick design iteration that we went through with promises this week.
In AngularJS (but this applies to any JavaScript), we have a function that calls the server to do a long running process.
function longProcess() { // dataservice returns a promise and we return that to our caller. return dataservice.longservice(); }
As this could potentially take nearly a minute, we want to add a waiting dialog.
AngularJS UI provides a modal dialog service $modal
function longProcess() { // create dialog var dialog = $modal.open({ templateUrl: 'wait.html' }); var promise = dataservice.longservice(); promise.then( function(){ // success dialog.close(); }, function() { // fail dialog.close(); } ); return promise; }
This works great.
But sometimes, the dialog flashes past too fast! While the user is still trying to read it, it disappears.
Before we run off into code, let's stop a do a bit of thinking.
What we need is to combine the original promise, with a second new timer promise (of say 5seconds). When both the service call has finished and the timer is up, we will resolve the promises.
So in pseudo code, it'd look like:
var p1 = service();
var p2 = $q.timer(5000);
var all = $q.all([p1,p2]);
all.then( /* resolve */ );
Note: $q is AngularJS' lightweight implementation of a Promise/A library Q. The pseudo-code assumption was that $q would provide a timer-based promise that detonates once time is up. In reality, $q doesn't provide such a method. But the $timeout service in AngularJS returns a promise for exactly this scenario.
function longProcess() { var dialog = $modal.open({ templateUrl: 'wait.html' }); var p1 = dataservice.longservice(); var p2 = $timeout(angular.noop, 5000); var arrayOfPromises = [p1, p2]; var promises = $q.all(arrayOfPromises); promises.then( function(){ // success dialog.close(); }, function() { // fail dialog.close(); } ); // returns a combined promise to our caller. return promises; }
Summary
The dialog opens and shows wait.html - it closes when the service is complete and when the timer has hit 5 seconds.