How organize asynchronous codes with Dojo? - javascript

I am creating a webapp with dynamic TABs (data from RESTful) and each TAB has a dgrid, which I get the columns from a RESTful and the rows from a RESTful, as well. I made everything works well with XHR and MemoryStore, but I now need to change from XHR to JsonRest, because I need to pass to the server, a HTTP Range.
I am having dificulties to organize my code with Asynchronous calls in Dojo. I will give you an example:
method1() - Sync
method2() - Async (JsonRest)
method3() - Sync
What the best way for the method3() be executed, only after method2() is ready?
I have found a class called WHEN. It seems nice. But how do you work with Async apps in dojo?
My biggest problem now: I can't separate my codes by methods, I need put all my code inside the JsonRest's promise function(THEN). Because inside THEN I can't access another method.

I would concur with the recommendation of using Dojo's promise implementation.
This might help you make some sense of it faster if you are not used to promises: http://jsfiddle.net/27jyf/9/. Another nice feature of this is error handling, I would encourage you to read on this after you have the basic sequencing down.
require(["dojo/Deferred", "dojo/when"], function(Deferred, when) {
var sayHello = function() { return 'hello' };
var sayWorld = function() {
var deferred = new Deferred();
window.setTimeout(function() {
deferred.resolve('world');
}, 1000);
return deferred.promise;
};
var sayBang = function() { return '!' };
//This will echo 'hello world !'
//That's probably how you want to sequence your methods here
var message = [];
message.push(sayHello());
sayWorld().then(function(part) {
message.push(part);
message.push(sayBang());
console.debug(message.join(' '));
});
//This will also echo 'hello world !'
//This probably not the syntax that you want here,
//but it shows how to sequence promises and what 'when' actually does
var message2 = [];
when(sayHello())
.then(function(part) {
message2.push(part);
return sayWorld();
})
.then(function(part) {
message2.push(part);
return when(sayBang());
})
.then(function(part) {
message2.push(part);
console.debug(message2.join(' '));
});
//Provided the behavior observed above, this will echo 'hello !'
//dojo/when allows you to use the same syntax for sync and async...
//but it does not let you magically write async operations in a sync syntax
//'world' will be pushed into the array a second later, after the message has already been echoed
var message3 = [];
message3.push(sayHello());
when(sayWorld(), function(part) {
message3.push(part);
});
message3.push(sayBang());
console.debug(message3.join(' '));
});

You can use the promise api to run async/sync methods in a specified order.

Related

add a function to a 3rd-party closure in javascript

Ok, I wouldn't think to do this in C#, but javascript is designed with much more flexibility in access.
there's a plugin like this
(function($)
{
...more stuff
var results={a:1,b:2} //this I need to modify
var someData={x:1}
send = function(){
//send results ajax
};
if(typeof beforeSend=='function')
beforeSend(someData) //hook to use results
})(jQuery)
So, in my own code, I have the function window.beforeSend = function(d){}
and it does have the someData which is in the scope I need to modify. But here's the question:
How can I modify the results var that's within the closure before it sends it.
I need to add
window.beforeSend = function(d){
window.quantumTunnelThroughScope.results['c']=1
}
The reason I need to do this is because I cannot modify the code of the plugin. Of course if I add the beforeSend within the closure, it works, but then I'm modifying the library which I'm not allowed to do in this case.
I've seen some awesome eval('this.xx' =function ) etc etc but I can't make it work.
EDIT: I clarified that actually it's a different var in the same scope that needs to be edited
No, there's no reasonable way for beforeSend to reach into that closure and modify results. results in the code presented is entirely private to code within that closure.
The unreasonable way to try to do it is to decompile and recompile the plugin function, via eval, and insert a call to a function before the beforeSend that lets us modify results:
(function($) {
$.run = function() {
// You mentioned "ajax," so let's make this
// asynchronous
setTimeout(function() {
var results = {
a: 1,
b: 2
};
var someData = { // Need to modify this
x: 1
};
send = function() {
//send results ajax
};
if (typeof beforeSend == 'function') {
beforeSend(someData); //hook to use results
}
console.log("in plugin, results = ", results);
}, 10);
};
})(jQuery)
window.modifyResults = function(d) {
return ["new", "results"];
};
window.beforeSend = function(r) {
r.c = 1;
};
jQuery.run = (function() {
// Function#toString, on nearly all browsers, returns the source
// code of he function (or something near to it) except on functions
// implemented in native code. We take that string and replace
// the "beforeSend(someData);" call with two calls, the first of
// which lets us modify the `results` variable. Then we use eval
// to turn that back into a function, and assign the result to
// where the plugin put its function originally.
return eval("(" + jQuery.run.toString().replace(
"beforeSend(someData);",
"results = modifyResults(results); beforeSend(someData);"
) + ")");
})();
jQuery.run();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
But may or may not work, depending on how the plugin is written, as it lifts it out of its original scope and recompiles it in the scope of our function updating jQuery.run.
I think I'd prefer to take the hit of modifying the plugin. :-)
Note: In the above, I've used a "static" jQuery function. If the plugin you're replacing provides an instance function, the kind you can call on jQuery instances, e.g. the bar in $(".foo").bar(), you'll find it on jQuery.fn instead of jQuery:
jQuery.fn.pluginFunction = eval(...);

AngularJS: Multiple async calls - how to

Sample
Please consider this Plunk.
Background
The Plunk is a seriously simplified sample of what I need to do. Basically I need to get a person record with validation result included. This result will also include class information, so that the controller can assign proper styling to indicate mandatory status (or not).
The issue
The most important function in the sample is this one, the self.Get will use the validation logic and result a result.
self.Get('0f8fad5b-d9cb-469f-a165-70867728950e').then(function(result){
$scope.person = result.person;
$scope.validationResult = result.ValidateResult;
});
As you can see (because the form has correct values) $scope.person is loaded correctly, the $scope.validationResult however is not.
The question
I suspect there's a timing issue with the consecutive async calls, how can I fix this Plunk so that everything works correctly?
Nesting async calls in each other would be 'one' solution, I guess, but given the number of calls being made, that would not solve everything and the code would become highly unreadable.
For multiple async calls I would suggest to use array of promises:
var promises = [];
promises.push(service1.get(...))
promises.push(service2.get(...))
promises.push(service3.get(...))
return $q.all(promises);
So, how do I convert the following code to use chaining, while keeping all dependencies intact?:
self.Get = function (personId) {
// 1. Init
var defer = $q.defer();
var asyncCallsResult = {};
// 2. Get person
var person = self.GetTestPerson();
asyncCallsResult.person = person;
self.LoadPersonDetailProxy(person).then(function(personDetailProxy) {
$scope.personDetailProxy = personDetailProxy;
});
validationService.ValidateAsync($scope.personDetailProxy).then(function (validateResult) {
asyncCallsResult.ValidateResult = validateResult;
});
defer.resolve(asyncCallsResult);
return defer.promise;
}

Which is a better way of writing callbacks?

Just by seeing what I've wrote now, I can see that one is much smaller, so in terms of code golf Option 2 is the better bet, but as far as which is cleaner, I prefer Option 1. I would really love the community's input on this.
Option 1
something_async({
success: function(data) {
console.log(data);
},
error: function(error) {
console.log(error);
}
});
Option 2
something_async(function(error,data){
if(error){
console.log(error);
}else{
console.log(data);
}
});
They are not exactly the same. Option 2 will still log the (data), whereas Option 1 will only log data on success. (Edit: At least it was that way before you changed the code)
That said, Option 1 is more readable. Programming is not / should not be a competition to see who can write the fewest lines that do the most things. The goal should always be to create maintainable, extendable (if necessary) code --- in my humble opinion.
Many people will find option#1 easier to read and to maintain - two different callback functions for two different purposes. It is commonly used by all Promise Libraries, where two arguments will be passed. Of course, the question Multiple arguments vs. options object is independent from that (while the object is useful in jQuery.ajax, it doesn't make sense for promise.then).
However, option#2 is Node.js convention (see also NodeGuide) and used in many libraries that are influenced by it, for example famous async.js. However, this convention is discussable, top google results I found are WekeRoad: NodeJS Callback Conventions and Stackoverflow: What is the suggested callback style for Node.js libraries?.
The reason for the single callback function with an error argument is that it always reminds the developer to handle errors, which is especially important in serverside applications. Many beginners at clientside ajax functions don't care forget about error handling for example, asking themselves why the success callback doesn't get invoked. On the other hand, promises with then-chaining are based on the optionality of error callbacks, propagating them to the next level - of course it still needs to be catched there.
In all honesty, I prefer to take them one step further, into Promises/Futures/Deferreds/etc...
Or (/and) go into a "custom event" queue, using a Moderator (or an observer/sub-pub, if there is good reason for one particular object to be the source for data).
This isn't a 100% percent of the time thing. Sometimes, you just need a single callback. However, if you have multiple views which need to react to a change (in model data, or to visualize user-interaction), then a single callback with a bunch of hard-coded results isn't appropriate.
moderator.listen("my-model:timeline_update", myView.update);
moderator.listen("ui:data_request", myModel.request);
button.onclick = function () { moderator.notify("ui:data_request", button.value); }
Things are now much less dependent upon one big callback and you can mix and match and reuse code.
If you want to hide the moderator, you can make it a part of your objects:
var A = function () {
var sys = null,
notify = function (msg, data) {
if (sys && sys.notify) { sys.notify(msg, data); }
},
listen = function (msg, callback) {
if (sys && sys.listen) { sys.listen(msg, callback); }
},
attach = function (messenger) { sys = messenger; };
return {
attach : attach
/* ... */
};
},
B = function () { /* ... */ },
shell = Moderator(),
a = A(),
b = B();
a.attach(shell);
b.attach(shell);
a.listen("do something", a.method.bind(a));
b.notify("do something", b.property);
If this looks a little familiar, it's similar behaviour to, say Backbone.js (except that they extend() the behaviour onto objects, and others will bind, where my example has simplified wrappers to show what's going on).
Promises would be the other big-win for usability, maintainable and easy to read code (as long as people know what a "promise" is -- basically it passes around an object which has the callback subscriptions).
// using jQuery's "Deferred"
var ImageLoader = function () {
var cache = {},
public_function = function (url) {
if (cache[url]) { return cache[url].promise(); }
var img = new Image(),
loading = $.Deferred(),
promise = loading.promise();
img.onload = function () { loading.resolve(img); };
img.onerror = function () { loading.reject("error"); };
img.src = url;
cache[url] = loading;
return promise;
};
return public_function;
};
// returns promises
var loadImage = ImageLoader(),
myImg = loadImage("//site.com/img.jpg");
myImg.done( lightbox.showImg );
myImg.done( function (img) { console.log(img.width); } );
Or
var blog_comments = [ /* ... */ ],
comments = BlogComments();
blog_comments.forEach(function (comment) {
var el = makeComment(comment.author, comment.text),
img = loadImage(comment.img);
img.done(el.showAvatar);
comments.add(el);
});
All of the cruft there is to show how powerful promises can be.
Look at the .forEach call there.
I'm using Image loading instead of AJAX, because it might seem a little more obvious in this case:
I can load hundreds of blog comments, if the same user makes multiple posts, the image is cached, and if not, I don't have to wait for images to load, or write nested callbacks. Images load in any order, but still appear in the right spots.
This is 100% applicable to AJAX calls, as well.
Promises have proven to be the way to go as far as async and libraries like bluebird embrace node-style callbacks (using the (err, value) signature). So it seems beneficial to utilize node-style callbacks.
But the examples in the question can be easily be converted into either format with the functions below. (untested)
function mapToNodeStyleCallback(callback) {
return {
success: function(data) {
return callback(null, data)
},
error: function(error) {
return callback(error)
}
}
}
function alterNodeStyleCallback(propertyFuncs) {
return function () {
var args = Array.prototype.slice.call(arguments)
var err = args.shift()
if (err) return propertyFuncs.err.apply(null, [err])
return propertyFuncs.success.apply(null, args)
}
}

Convert async calls to sync?

I got problems to handle async calls.
For example I want to load some modules dynamically with requirejs.
Currently I use the subscriber-publisher pattern. Unfortunately this makes my code
in some situation really confusing...:
imagine there is a working event system in the object
var loader = {
load: function(modules) {
// do a async requirejs call
require(modules, function(){
// map arguments to normal array
var modules = [].slice().call(arguments);
// fire loaded event, pass modules
this.trigger('loaded', modules);
}.bind(this));
}
};
var parent = {
// do some initialization work
initialize: function() {
// execute the second initialization when our modules have finished loading async
loader.on('loaded', this.secondInitialize, this);
// require the given modules in the array
loader.load(['one', 'two', 'three']);
},
secondInitialize: function(modules) {
var three = new modules[2]();
// do something with the 'three' module
}
};
As you see this is really confusing.
Are there any other design patterns which allow handsome handling of async calls?
Look into the jQuery Deferred object. (Even without jq, most libraries have an implementation of javascript promises)
With it you can do something like this:
var loadingOne = getLibOne(); //returns a jquery deferred promise
var loadingTwo = getLibTwo(); //returns another one
var loadingAllLibraries = $.when(loadingOne, loadingTwo);
loadingAllLibraries.done(function(lib1, lib2) {
//... stuff
});
Not exactly your scenario but you get the idea. It becomes relatively easy to compose asynchronous atoms.

Usage of Observable pattern in JavaScript

function Observer() {
this.fns = [];
}
Observer.prototype = {
subscribe : function(fn) {
this.fns.push(fn);
},
unsubscribe : function(fn) {
this.fns = this.fns.filter(
function(el) {
if ( el !== fn ) {
return el;
}
}
);
},
fire : function(o, thisObj) {
var scope = thisObj || window;
this.fns.forEach(
function(el) {
el.call(scope, o);
}
);
}
};
var fn = function() {};
var o = new Observer;
o.subscribe(fn);
o.fire('here is my data');
o.unsubscribe(fn);
I am not able to understand the whole concept behind this. I want to implement this pattern in my project. I have a view where the form gets submitted and it calls an WebService and returns me response.
If i have to implement this in my project where this a simple request and response... how would i go about with it? i understand you notify your observer when there is a change... let's take i make a request to my API and i get the response back... now i want it to get notified to my view back through observable pattern
Observer appears to be a constructor that you call with var o = new Observer(); then o will be an object with a reference to a bunch of functions. you add functions to the list via subscribe. and remove them from the list via unsubscribe
then the whole point of it all is the "fire" method which will loop through the function list then call each of the functions one by one . "observer pattern" appears to be a lot like the singleton pattern
Are you familiar with the "watch" method in JavaScript? its a method supported via Firefox that you can use on any object.
document.myform.myfield.watch('value', function (v) {
alert(v);
return v;
})
then whenever the value of the object changes, the watch function is called. so basically the concept behind the observer pattern is that you want to basically simulate Firefox's watch method in a cross-browser fashion
you toss a reference to a bunch of functions or objects into subscribed list.then have Observer.fire call a callback method on each of the watched objects or functions. that way if the user preforms some sort of action such as clicking, then the whole list of functions would be updated via a callback function
I hope this helps.
If you only want to do a simple request then in jQuery (such as with $.ajax(...) or $.get(...)) that would look like this:
var requestUrl = "text.html";
// Callback is defined here
var viewCallback = function(data) {
// this will be called when the request is done
console.log('view is notified');
console.log('data looks like this:');
console.log(data);
// you could chain method calls to other callbacks here if you'd like
};
// Request is done here
$.ajax({
url: requestUrl,
}).done(viewCallback);
Most of the time you only want to do one thing when doing a request for which the above is enough code. Using javascript libraries such as jQuery or mootools will abstract away the oddities with the XMLHttpRequest object.
However if you want to do something much more advanced I'd recommend you look at libraries that do this sort of thing such as Radio.js.

Categories