Convert async calls to sync? - javascript

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.

Related

Does anyone know of a JS Chaining library that allows for deferred execution of methods? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 1 year ago.
Improve this question
I'm looking for a library that allows me to easily chain together methods but defer their execution until arguments are provided further along in the chain:
chain
.scanDirectory ( '/path/to/scan' )
.recursively()
.for ( /\.js$/i )
.cache()
.provideTo ( '0.locals' )
.as ( 'scripts' )
.defer();
The important thing is that the code behind the scanDirectory function isn't actually called until it's defined that it should be recursive and looking for .js files.
I'm not quite sure how to logically set this up so that I can do something like:
chain
.scanDirectory( '/path/to/scan' )
.scanDirectory( '/another/path' )
.for ( /\.js$/i ) // provided to both paths above?
.doSomethingElse()
which is why I'm looking for a library that may have more mature ideas that accomplish this :)
This post talks about types of execution in JS, there are links to relevant libraries in the end of it
Execution in JavaScript
You have two types of execution in JS:
Synchronous - stuff that happens right when it's called
Asynchronous - stuff that happens when after the current code is done running, also what you refer to as deferred.
Synchronous
Synchronously, you can push actions and parameters to a queue structure, and run them with a .run command.
You can do something like:
var chain = function(){
var queue = []; // hold all the functions
function a(param){
//do stuff, knowing a is set, may also access other params functions set
}
return {
a:function(someParam){
queue.push({action:a,param:someParam});
return this;
},
... // more methods
run:function(){
queue.forEach(function(elem){ // on each item
elem.action.apply(null,param);//call the function on that item
});
}
};
}
This will execute all the functions in the queue when you call run, syntax would be something like
chain().a(15).a(17).run();
Asynchronous
You can simply set a timeout, you don't need to use something like .run for this.
var chainAsync = function(){
// no need for queue
function a(param){
//do stuff, knowing a is set, may also access other params functions set
}
return {
a:function(someParam){
setTimeout(a,0,someParam);
return this;
},
... // more methods
};
}
Usage would be something like
chain().a(16).a(17);
Some issues:
If you want to share parameters between functions, you can store them somewhere in the object itself (have a var state in addition to the queue).
It's either sync, or async. You can't detect one or the other by context. Workarounds are being built for ES6.
More resources
For some implementation of something similar, you can see this question where I implement something similar.
Promises tutorial - promises let you use this type of execution called CPS (continuation passing style) to great effect.
Another nice post on promises.
Bluebird - the fastest and likely best promise library.
Q - probably the most well known and widely used library for chaining execution and promises in JavaScript. Used it several times myself.
Question here on promises and their benefits.
How does basic chaining work in JavaScript - another relevant question here in SO.
Note sure you'll find an all-around working solution for this.
Looks like you're looking for a generic solution to something that would require to have been already baked into the library. I mean, I'm sure there are libraries that have this functionality, but they wouldn't hook auto-magically on other libraries (expect if they have specifically implemented overrides for the right version of the libraries you want to target, maybe).
However, in some scenarios, you may want to look at the Stream.js library, which probably covers enough data-related cases to make it interesting for you:
I don't know whether there's a library to build such methods, but you can easily build that feature yourself. Basically, it will be a settings object with setter methods and one execute function (in your case, defer).
function Scanner() {
this.dirs = [];
this.recurse = false;
this.search = "";
this.cache = false;
this.to = "";
this.name = "";
}
Scanner.prototype = {
scanDirectory: function(dir) {
this.dirs.push(dir);
return this,
},
recursively: function() {
this.recurse = true;
return this;
},
for: function(name) {
this.search = name;
return thsi;
},
cache: function() {
this.cache = true;
return this;
},
provideTo: function(service) {
this.to = service;
return this;
},
as: function(name) {
this.name = name;
return this;
},
defer: function() {
// now, do something with all the given settings here
},
doSomethingElse: function() {
// now, do something else with all the given settings here
}
};
That's the standard way to build a fluent interface. Of course, you could also create a helper function to which you pass a methodname-to-setting map which writes the methods for you if it gets too lengthy :-)
You need a queue to maintain the async and sync-ness of your method chain.
Here is an implementation using jQuery.queue I did for a project:
function createChainable(options) {
var queue = [];
var chainable = {
method1 : function () {
queue.push(function(done){
// code here
done();
});
return chainable;
},
exec1 : function () {
queue.push(function(done){
// code here
done();
});
$.queue(ELEMENT, QUEUE_NAME, queue).dequeue(QUEUE_NAME);
return chainable;
}
};
return chainable;
}
As #Jordan Doyle said in his comment:
Just return this
So every method in your objects should return the object in the return statement so that you can chain on another method.
For example:
var obj = new (function(){
this.methOne = function(){
//...
return this;
}
this.methTwo = function(){
//...
return this;
}
this.methThree = function(){
//...
return this;
}
})();
//So you can do:
obj.methOne().methTwo().methThree();

How organize asynchronous codes with Dojo?

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.

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)
}
}

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.

Coordinating parallel execution in node.js

The event-driven programming model of node.js makes it somewhat tricky to coordinate the program flow.
Simple sequential execution gets turned into nested callbacks, which is easy enough (though a bit convoluted to write down).
But how about parallel execution? Say you have three tasks A,B,C that can run in parallel and when they are done, you want to send their results to task D.
With a fork/join model this would be
fork A
fork B
fork C
join A,B,C, run D
How do I write that in node.js ? Are there any best practices or cookbooks? Do I have to hand-roll a solution every time, or is there some library with helpers for this?
Nothing is truly parallel in node.js since it is single threaded. However, multiple events can be scheduled and run in a sequence you can't determine beforehand. And some things like database access are actually "parallel" in that the database queries themselves are run in separate threads but are re-integrated into the event stream when completed.
So, how do you schedule a callback on multiple event handlers? Well, this is one common technique used in animations in browser side javascript: use a variable to track the completion.
This sounds like a hack and it is, and it sounds potentially messy leaving a bunch of global variables around doing the tracking and in a lesser language it would be. But in javascript we can use closures:
function fork (async_calls, shared_callback) {
var counter = async_calls.length;
var callback = function () {
counter --;
if (counter == 0) {
shared_callback()
}
}
for (var i=0;i<async_calls.length;i++) {
async_calls[i](callback);
}
}
// usage:
fork([A,B,C],D);
In the example above we keep the code simple by assuming the async and callback functions require no arguments. You can of course modify the code to pass arguments to the async functions and have the callback function accumulate results and pass it to the shared_callback function.
Additional answer:
Actually, even as is, that fork() function can already pass arguments to the async functions using a closure:
fork([
function(callback){ A(1,2,callback) },
function(callback){ B(1,callback) },
function(callback){ C(1,2,callback) }
],D);
the only thing left to do is to accumulate the results from A,B,C and pass them on to D.
Even more additional answer:
I couldn't resist. Kept thinking about this during breakfast. Here's an implementation of fork() that accumulates results (usually passed as arguments to the callback function):
function fork (async_calls, shared_callback) {
var counter = async_calls.length;
var all_results = [];
function makeCallback (index) {
return function () {
counter --;
var results = [];
// we use the arguments object here because some callbacks
// in Node pass in multiple arguments as result.
for (var i=0;i<arguments.length;i++) {
results.push(arguments[i]);
}
all_results[index] = results;
if (counter == 0) {
shared_callback(all_results);
}
}
}
for (var i=0;i<async_calls.length;i++) {
async_calls[i](makeCallback(i));
}
}
That was easy enough. This makes fork() fairly general purpose and can be used to synchronize multiple non-homogeneous events.
Example usage in Node.js:
// Read 3 files in parallel and process them together:
function A (c){ fs.readFile('file1',c) };
function B (c){ fs.readFile('file2',c) };
function C (c){ fs.readFile('file3',c) };
function D (result) {
file1data = result[0][1];
file2data = result[1][1];
file3data = result[2][1];
// process the files together here
}
fork([A,B,C],D);
Update
This code was written before the existence of libraries like async.js or the various promise based libraries. I'd like to believe that async.js was inspired by this but I don't have any proof of it. Anyway.. if you're thinking of doing this today take a look at async.js or promises. Just consider the answer above a good explanation/illustration of how things like async.parallel work.
For completeness sake the following is how you'd do it with async.parallel:
var async = require('async');
async.parallel([A,B,C],D);
Note that async.parallel works exactly the same as the fork function we implemented above. The main difference is it passes an error as the first argument to D and the callback as the second argument as per node.js convention.
Using promises, we'd write it as follows:
// Assuming A, B & C return a promise instead of accepting a callback
Promise.all([A,B,C]).then(D);
I believe that now the "async" module provides this parallel functionality and is roughly the same as the fork function above.
The futures module has a submodule called join that I have liked to use:
Joins asynchronous calls together similar to how pthread_join works for threads.
The readme shows some good examples of using it freestyle or using the future submodule using the Promise pattern. Example from the docs:
var Join = require('join')
, join = Join()
, callbackA = join.add()
, callbackB = join.add()
, callbackC = join.add();
function abcComplete(aArgs, bArgs, cArgs) {
console.log(aArgs[1] + bArgs[1] + cArgs[1]);
}
setTimeout(function () {
callbackA(null, 'Hello');
}, 300);
setTimeout(function () {
callbackB(null, 'World');
}, 500);
setTimeout(function () {
callbackC(null, '!');
}, 400);
// this must be called after all
join.when(abcComplete);
A simple solution might be possible here: http://howtonode.org/control-flow-part-ii scroll to Parallel actions. Another way would be to have A,B, and C all share the same callback function, have that function have an global or at least out-of-the-function incrementor, if all three have called the callback then let it run D, ofcourse you will have to store the results of A,B, and C somewhere as well.
Another option could be the Step module for Node: https://github.com/creationix/step
You may want to try this tiny library: https://www.npmjs.com/package/parallel-io
In addition to popular promises and async-library, there is 3rd elegant way - using "wiring":
var l = new Wire();
funcA(l.branch('post'));
funcB(l.branch('comments'));
funcC(l.branch('links'));
l.success(function(results) {
// result will be object with results:
// { post: ..., comments: ..., links: ...}
});
https://github.com/garmoshka-mo/mo-wire

Categories