Traversing promises in Q - javascript

In Scala I can take a list of values, map a future-returning function across them, and get back a future that will collect the values of those futures into a list (or fail with the first error). More concretely:
import scala.concurrent._
import scala.concurrent.ExecutionContext.Implicits.global
def doSomething(i: Int): Future[Int] = future(i + 1) // Not really doing much.
val incremented = Future.traverse(List(1, 2, 3))(doSomething)
In this case the result will just be the incremented list:
scala> incremented.onSuccess { case xs => println(xs) }
List(2, 3, 4)
I could alternatively create a list of futures and then turn them into a future containing the same result:
val incremented = Future.sequence(List(1, 2, 3).map(doSomething))
This will give me the same thing, but it creates an extra intermediate collection and is a little more noisy.
I want to do something like this with promises in Q, and it looks like Q.all is more or less sequence:
function doSomething(i) { return Q.fcall(function () { return i + 1; }); }
Q.all([1, 2, 3].map(doSomething)).then(function (xs) { console.log(xs) })
Is there a way for me to write a more traverse-like version? It's such a basic operation that it seems like there must be a way to do it, but this is my first afternoon with Q and I'm still working through all the overloads of fcall and friends.

Not directly an answer to your question, but AngularJS uses an extremely reduced version of Q ($q), so there you definitely have to implement this behavior yourself.
Here's one approach:
var traverse = function(fn /*values*/) {
var values = _.rest(arguments);
var promises = _.map(values, fn);
return $q.all(promises);
};
Full example: http://plnkr.co/edit/PGp7QbQYMjOknJwSEn8E
Or with separate parameter lists as in Scala:
var traverse = function(/*values*/) {
var values = arguments;
return function(fn) {
var promises = _.map(values, fn);
return $q.all(promises);
}
};
Full example: http://plnkr.co/edit/pWoGGaZobbx61tAmUWr9?p=preview

You can use Promise Chaining + Static values (instead of promises) for methods and do something like:
Q.all([1,2,3])
.then(function(xs) {
return _(xs).map(doSomething)
})
.then(function(xs) {
console.log(xs);
});
If you want a traverse function like that one, you can easily implement it yourself
Hope it helps!

Related

transpiler battle: breaking out of nested function, with vs without throw

I have just finished writing "version 0" of my first (toy) transpiler. It works. It turns a string of "pseudo JavaScript" (JavaScript with an additional feature) into a string of runnable JavaScript. Now, I want to improve it.
The work area possibly most interesting for other SO users is this: The compiled code (i.e., output of my transpiler) does not heed a coding style recommendation as given in an accepted answer to some earlier SO question. If I would have at my hands a second transpiler where that coding style recommendation is heeded, I could make an informed decision regarding which branch is more promising to continue to develop on - I'd like to compare the 2 braches regarding performance, development time needed, amount of bugs, and so on, and decide based on that.
Let me tell you about the "additional JS feature" my transpiler deals with: "nested return". Consider closures / nested functions like so
function myOuterFunc(){
... code ...
function innerFunc(){
... code ...
}
... code ...
}
(note that above '...code...' is supposed to include every possible JS code including more nested function declarations, so myOuterFunc is not necessarily the direct parent of innerFunc)
In above situation, suppose you desire to return a result from myOuterFunc from somewhere inside - not necessarily directly inside - innerFunc
With "nested return" implemented, you could then write simply
return.myOuterFunc result
Here is an exmalpe of a (not-runnable) function using this feature and doing something meaningful
function multiDimensionalFind(isNeedle, haystack) {
// haystack is an array of arrays
// loop (recursively) through all ways of picking one element from each array in haystack
// feed the picked elements as array to isNeedle and return immediately when isNeedle gives true
// with those picked elements being the result, i.e. the 'found needle'
var LEVEL = haystack.length;
function inner(stack) {
var level = stack.length;
if (level >= LEVEL) {
if (isNeedle(stack)) return.multiDimensionalFind stack;
} else {
var arr = haystack[level];
for (var i = 0; i < arr.length; i++) {
inner(stack.concat([arr[i]]));
}
}
}
inner([]);
return 'not found'
}
And here is the (runnable) code my transpiler automatically produces from that (comments were added/remove later, obviously), followed by some code testing if that function does what it claims to do (and it does, as you can convince yourself.)
///////////// the function /////////////////
function multiDimensionalFind(isNeedle, haystack) {
try {
var LEVEL = haystack.length;
function inner(stack) {
var level = stack.length;
if (level >= LEVEL) {
if (isNeedle(stack)) throw stack;
} else {
var arr = haystack[level];
for (var i = 0; i < arr.length; i++) {
inner(stack.concat([arr[i]]));
}
}
}
inner([]);
return 'not found'
} catch(e){
// make sure "genuine" errors don't get destroyed or mishandled
if (e instanceof Error) throw e; else return e;
}
}
////////////////// test it //////////////////
content = document.getElementById('content');
function log2console(){
var digits = [0,1];
var haystack = [digits,digits,digits,digits,digits];
var str = '';
function isNeedle(stack){
str = str + ', ' + stack.join('')
return false;
}
multiDimensionalFind(isNeedle, haystack);
content.textContent = str;
}
function find71529(){ // second button
var digits = [0,1,2,3,4,5,6,7,8,9]
var haystack = [digits,digits,digits,digits,digits]
function isNeedle(stack){
return stack.reduce(function(b,i){ return 10*b+i; }, 0) === 71529
// returns true iff the stack contains [7,1,5,2,9]
}
content.textContent = multiDimensionalFind(
isNeedle, haystack
).join('_')
}
<button onclick='log2console()'>print binary numbers with 5 digits</button>
<br>
<button onclick='find71529()'>find something is 5d space</button>
<div id='content'></div>
You can play around with my transpiler in this fiddle here. I'm using the esprima library, the escodegen.js library on top of esprima, a teeny tiny work in progress abstract syntax tree generation library of my own (see the script tags in the fiddle). The code which is not library, and not UI code, i.e. the "real meat" of the transpiler has less than 100 lines (see function transpile). So this might be a lot less complicated than you thought.
I can't remember where I had seen the style recommendation, but I am certain that it was actually in multiple places. If you know or come across one such question, I invite you to be so kind to put the link into a comment under the question, I will mark useful. So far, there is one link, thank you Barmar.
You might ask why I even bothered to write a "non-compliant" transpiler first, and did not go for the "compliant" version straight away. That has to do with the estimated amount of work. I estimate the amount of work to be much larger for the "compliant" version. So much so, that it didn't really seem worthwhile to embark on such an endeavor. I would very much like to know whether this assessment of the amount of work is correct or incorrect. Thus the question. Please do not insinuate a rhetorical, or even a dishonest motive for the question; however weird it might sound to some, it really is the case that I'd like to be proven wrong, so please be so kind not to assume I'm "just saying that" for whatever reason, you'd be doing me an injustice. This is, of all the questions I asked on SO so far, by far the one I've put the most work into. And, if you ask me, it is by far the best question I have ever asked here.
Apart from someone assisting me in writing the "compliant" version of the transpiler, I'm also interested (albeit to a lesser degree) in anything objectively demonstrable which stands a chance to convince me that the "non-compliant" way is the wrong way. Speed tests (with links to jsperf), reproducible bug reports, things of that sort.
I should mention the speed tests I have done myself so far:
first test, second test
loosely related question
The better way really is to use return (if you can't completely refactor the tower). It makes it clear what you're doing and when you're returning a value from the intermediate functions; you can tell by looking at those functions where the result may be provided. In contrast, using throw is invisible in those intermediate layers; it magically bypassing them in a way designed for error conditions.
If you don't want to do that, I don't think you have a reasonable alternative other than throw. I wondered about going down the route of generator functions or similar, but I think that would just complicate things more, not less.
Using return doesn't markedly complicate the example code, and does (to my eye) make it clearer what's going on and when results are potentially expected.
function wrapper(){
function first(){
function second(){
function third(){
doStuff4();
some loop {
var result = ...
if (something) return result;
}
}
doStuff2();
let result = third();
if (result) {
return result;
}
doStuff3();
return third();
}
doStuff1();
return second();
}
return first() || "not found";
}
(In the above, result is tested for truthiness; substitute something else if appropriate.)
Ok, here is another approach with use of all async power of JavaScript... So basically I've recreated your nested functions but with use of Promise/await technique. You will get result only once, the first time you'll resolve it from any level of nested functions. Everything else will be GC. Check it out:
// Create async function
(async () => {
const fnStack = (val) => {
return new Promise((resolve, reject) => {
// Worker functions.
// Could be async!
const doStuff1 = (val) => val + 1;
const doStuff2 = (val) => val * 2;
const doStuff3 = (val) => val * -1; // This will not affect result
const doStuff4 = (val) => val + 1000;
// Nested hell
function first() {
function second() {
function third() {
val = doStuff4(val);
// Some loop
for(let i = 0; i < 1000; i++) {
if(i === 500) {
// Here we got our result
// Resolve it!
resolve(val);
}
}
}
val = doStuff2(val);
third();
// Below code will not affect
// resolved result in third() above
val = doStuff3(val);
third();
}
val = doStuff1(val);
second();
}
//
first();
});
}
// Run and get value
const val = await fnStack(5);
// We get our result ones
console.log(val);
})();
I think you should use arrays;
const funcs = [first, second, third];
for(let i = 0; i < funcs.length; ++i){
const result = funcs[i]();
if (result) break;
}
You should return only from function that has the result.
Sometime later, when I get around to it, I'll add instructions here on how to use my abstract syntax tree generation library which I used for my transpiler, maybe even start a little towards the other version, maybe explaining in more detail what the things are which make me think that it is more work.
old version follows (will be deleted soon)
If the feature is used multiple times we'll need something like this:
function NestedThrowee(funcName, value){
this.funcName = funcName;
this.value = value;
}
return.someFunctionName someReturnValue (before compilation) will give (after compliation) something like
var toBeThrown = new NestedThrowee("someFunctionName", someReturnValue);
And inside the generated catch block
if (e instanceof Error){
throw e; // re-throw "genuine" Error
} else {
if (e instance of NestedThrowee){
if (e.funcName === ... the name of the function to which
this catch block here belongs ...) return e.value;
throw new Error('something happened which mathheadinclouds deemed impossible');
}
In the general case, it is necessary to wrap the result (or 'throwee') like shown above, because there could be multiple, possibly nested "nested returns", and we have to take care that the catch phrase and caught object of type NestedThrowee match (by function name).

checking thruthness of overwritten valueOf not working

I want to create a similar construction in my code.
var inList = findItem(list, data);
if(!inList) {
var item = inList.item;
}
function findItem(list, data) {
var item = list.find("[data-day='"+data.day+"']")
// more code.
// conditional return
return {item: item, valueOf:function(){return false}};
}
But it doesn't work because overwriting valueOf doesn't play nicely with a simple truthfull check (in the way that I want it to work).
and having code like if(inList == false){} looks less clean imo. Is there a way to make this work?
Boolean checks don't invoke valueOf - all objects are considered truthy. If you want to circumvent that, you'll have to invoke it yourself explicitly:
if (!inList.valueOf()) …
You should not depend on code that uses valueOf,
if you wanted to do something where you are returning an object,
just add another property instead.
var findResult = findItem(list, data);
if(!findResult.found) {
var item = findResult.item;
}
function findItem(list, data) {
var item = list.find("[data-day='"+data.day+"']");
// more code.
// conditional return
return {item: item, found: false};
}
Then again, I forgot what I was doing 5 years ago.

walking a tree with Promises

I have a tree structure that I want to walk using Promises, and I haven't figured out the right code pattern for it.
Assume that we're given node names, and the act of converting a node name to a node is an asynchronous process (e.g. involves a web access). Also assume that each node contains a (possibly empty) list of children names:
function getNodeAsync(node_name) {
// returns a Promise that produces a node
}
function childrenNamesOf(node) {
// returns a list of child node names
}
What I want to end up with a method with this signature:
function walkTree(root_name, visit_fn) {
// call visit_fn(root_node), then call walkTree() on each of the
// childrenNamesOf(root_node), returning a Promise that is fulfilled
// after the root_node and all of its children have been visited.
}
that returns a Promise that's fulfilled after the root node and all of its children have been visited, so it might be called as follows:
walkTree("grandpa", function(node) { console.log("visiting " + node.name); })
.then(function(nodes) { console.log("found " + nodes.length + " nodes.")});
update
I've create a gist that shows my first attempt. My (slightly buggy) implementation for walkTree() is:
function walkTree(node_name, visit_fn) {
return getNodeAsync(node_name)
.then(function(node) {
visit_fn(node);
var child_names = childrenNamesOf(node);
var promises = child_names.map(function(child_name) {
walkTree(child_name, visit_fn);
});
return Promise.all(promises);
});
};
This visits the nodes in the correct order, but the outermost Promise resolves before all the sub-nodes have been visited. See the gist for full details.
And as #MinusFour points out, using this technique to flatten the list of nodes is rather pointless. In fact, I really just want the final promise to fire when all the nodes have been visited, so a more realistic use case is:
walkTree("grandpa", function(node) { console.log("visiting " + node.name); })
.then(function() { console.log("finished walking the tree")});
Well it isn't much of a problem to handle a function call for each node, but gathering the node values is kind of a problem. Kind of hard to walk that tree, your best bet would be to map it to a tree with no eventual values. You could use something like:
function buildTree(root_name) {
var prom = getNodeAsync(root_name);
return Promise.all([prom, prom.then(function(n){
return Promise.all(childrenNamesOf(n).map(child => buildTree(child)))
})]);
}
From there on you do:
var flatTree = buildTree(root_name).then(flatArray);
flatTree.then(nodes => nodes.forEach(visit_fn));
flatTree.then(nodes => whateverYouWantToDoWithNodes);
To flatten the array you could use:
function flatArray(nodes){
if(Array.isArray(nodes) && nodes.length){
return nodes.reduce(function(n, a){
return flatArray(n).concat(flatArray(a));
});
} else {
return Array.isArray(nodes) ? nodes : [nodes];
}
}
To be honest, it's pointless to have the tree walker if you want a list of nodes you are better up flattening it up and then iterating the elements, but you can walk the array tree if you want.
Despite what I said in the O.P, I don't really care about the return values of the final promise, but I do want to wait until all the nodes have been traversed.
The problem with the original attempt was simply a missing return statement in the map() function. (Despite appearances, this is essentially structurally identical to #MinusFour's answer.) Corrected form below:
function walkTree(node_name, visit_fn) {
return getNodeAsync(node_name)
.then(function(node) {
visit_fn(node);
var child_names = childrenNamesOf(node);
var promises = child_names.map(function(child_name) {
return walkTree(child_name, visit_fn);
});
return Promise.all(promises);
});
};
Here are two use cases for walkTree(). The first simply prints the nodes in order then announces when the tree walk is finished:
walkTree("grandpa", function(node) { console.log("visiting " + node.name); })
.then(function() { console.log("finished walking the tree")});
The second creates a flat list of nodes, made available when the tree walk completes:
var nodes = [];
walkTree("grandpa", function(node) { nodes.push(node) })
.then(function() { console.log('found', nodes.length, 'nodes);
console.log('nodes = ', nodes); });

Dynamically adding sequential actions using deferreds

Here is my current code: https://gist.github.com/benjamw/f6d5d682caddd4c1e506
What I'm trying to do is: based on what the URL is when the user hits the page, pull down different data from the server, and when that's all done, render the page with Hogan.
My problem is that step B needs data from step C to render properly, and step C needs data from step B to pull the right data, but step C can be pulled by itself if that's the page the user requests (the data needed by C to pull properly is part of the URL when going directly to C).
I have a Deferred being stored in Thing that gets resolved in the various pull steps and triggers the render, but in pull_B, I don't want it resolved until it gets and cleans data from both pull_B and pull_C. But if the user goes direct through C, then I want it to resolve just fine.
How can I dynamically add a promise to the when in the init() function when the process goes through the B path to include the C path?
Or, how can I make B pass it's promise into C and then resolve it there, but still keep the functionality of being able to go through C itself, and have it still resolve the main deferred object without going through B first?
I'm trying really hard not to drop into callback hell for this, but I'm finding it difficult to do so.
The crux of the problem is clearly the relationship between B and C, which, in summary, appears to be :
If B, pull-C().then(pull-B);
If C, pull-B().then(pull-C);
In the current attempt, you are running into problems by trying to code the flow logic inside pull-B() and pull-C(), which is ultimately possible but complex.
A simpler strategy is to make the pull_X() functions very simple promise-returning data retrievers, and to code the flow logic and data cleanups inside the switch/case structure in .init(). You will see what I mean in the code below.
Apart from being simpler, this will also avoid any chance of circular dependencies between pull_B() and pull_C().
By fully exploiting promises, you will also find that :
the need for this.dfd disappears (in favour of returning promises from functions).
the need for this.data disappears (in favour of allowing promises to deliver the data).
the need for a callback to be passed to .pull() disappears (in favour of chaining .then() in the caller). Thus, callback hell disappears.
Try this :
(function($) {
"use strict";
/**
* The Thing
*
* #constructor
*/
function Thing( ) {
/* properties */
this.url = [
/* path */,
/* id */
];
}
Thing.prototype.pull = function(url, args, type) {
return $.ajax({
type: type || 'GET',
url: foo.root + url,
data: $.extend({}, args || {}),
dataType: 'json'
});
};
Thing.prototype.pull_As = function() {
return this.pull('a', this.query);
};
Thing.prototype.pull_A = function() {
this.nav = false;
return this.pull('a/'+ this.url[2]);
};
Thing.prototype.pull_B = function() {
return this.pull('b/' + this.url[2]);
};
Thing.prototype.pull_C = function(id) {
return this.pull('c/' + id || this.url[2]);
};
Thing.prototype.pull_D = function() {
return this.pull_As();
};
Thing.prototype.render = function(data) {
var i, len, html,
that = foo.thing, /* because 'this' is the promise object */
title = document.title.split('|');
for (i = 0, len = title.length; i < len; i += 1) {
title[i] = $.trim(title[i]);
}
title[0] = $.trim(that.title);
document.title = title.join(' | ');
html = Hogan.wrapper.render({
'data': data,
});
$('#thing_wrapper').empty().append(html);
};
Thing.prototype.init = function( ) {
var promise,
that = this;
switch (this.url[1].toLowerCase( )) {
case 'a':
promise = this.pull_A().then(function(data_A) {
/* ... do A data cleanup */
return data_A;//will be passed through to .render()
});
break;
case 'b':
promise = this.pull_C().then(function(data_C) {
//Here an inner promise chain is formed, allowing data_C, as well as data_B, to be accessed by the innermost function.
return that.pull_B().then(function(data_B) {
var data = ...;//some merge of data_B and data_C
return data;//will be passed through to .render()
});
});
break;
case 'c':
var id = ???;
promise = this.pull_C(id).then(function(data_C) {
/* ... do C data cleanup */
return data_C;//will be passed through to .render()
});
break;
case '':
default:
promise = this.pull_D().then(function(data_D) {
/* ... do D data cleanup */
return data_D;//will be passed through to .render()
});
}
promise.then(this.render, console.error.bind(console));
};
window.Thing = Thing;
})(jQuery);
Note in particular that a promise or data is returned from the various functions.
I doubt my attempt is 100% correct. The overall structure should be fine, though you will need to take a close look at the detail. I may have misunderstood the B/C dependencies. With luck, it will be simpler than what I have coded.
Edit: code amended in light of comments below.

can I emulate a C-like array of pointers in javascript?

I'd like to be able to store the addresses of a bunch of different variables in an array. This allows me to access the variables by name or iterate through them if I need to. Is this possible in JS?
(function(ns){
ns.obj = new function(){
var foo = "foo";
var bar = "bar";
//i really want this:
//var ary = [&foo, &bar];
var ary = [foo, bar];
this.print = function() {
console.log( foo );
console.log( bar );
}
this.setFoo = function( newFoo ) {
//i really want this:
//*(ary[0]) = newFoo;
ary[0] = newFoo;
}
this.printAry = function() {
for( var i=0; i < ary.length; ++i ) {
console.log( ary[i] );
}
}
};
}(window.ns = window.ns || {}) );
ns.obj.print();
ns.obj.setFoo("newfoo!");
ns.obj.printAry();
ns.obj.print();
I looked at this:
JavaScript array of pointers like in C++
But I'd like to be able to use an element of ary on the LHS of an assignment and I don't think that example works in this situation.
WHY ON EARTH DO I WANT TO DO THIS?
A lot of comments so far have (rightfully) asked why I'd want to do this. I'm dealing with a proprietary API that involves an asynchronous object initialization mechanism. Basically I create an instance of an object and then pass it to this initializer to be able to actually use it. The initializer includes a field for an onSuccess handler to notify of successful initialization. My fully initialized object is passed as an argument into this success handler so that I can grab a reference to it.
I'm then free to initialize my next object. It looks kinda like this:
var a = new api.ApiObject();
var b = new api.ApiObject();
var c = new api.ApiObject();
var d = new api.ApiObject();
//omg this is ugly
api.initializeObject( {
objToInit: a,
onSuccess: function(args) {
a = args.obj;
api.initializeObject( {
objToInit: b,
onSuccess: function(args) {
b = args.obj;
api.initializeObject( {
objToInit: c,
onSuccess: function(args) {
c = args.obj;
api.initializeObject( {
objToInit: d,
onSuccess: function(args) {
d = args.obj;
}
} );
}
} );
}
} );
}
} );
a.doCoolStuff();
//and so on
This deeply nested mess just gets worse as I add more api.ApiObjects(). So what do I do to fix this? I can't change the API, but maybe a recursive function could help:
//maybe a recursive function could make this more concise?
function doInitialize( ary ) {
api.initializeObject( {
objToInit: ary[0];
onSuccess: function(args) {
//i'd like to assign this passed in reference to my local
//reference outside this function (var a, b, etc).
//An array of pointers would be useful here.
//how else can I get this assigned out, cuz this doesn't work...
ary[0] = args.obj;
if( ary.length > 1 ) {
ary.splice( 0, 1 );
doInitialize( ary );
}
}
}
}
doInitialize( [a,b,c,d] );
//this won't work because I don't have a reference to the fully initialized object
a.doCoolStuff();
So maybe the better question is: is there an established pattern to deal with asynchronous success chaining like this? I think I've seen other public JS frameworks (like dojo) use this sort of onSuccess chaining... how do I make this not ugly?
I might suggest that if your primary purpose for this is convenience as regards nesting of asynchronous callbacks, that you should consider a deferred/promise system.
I've written a couple of different promise libraries by hand.
jQuery comes with one built in (as do most "ajax libraries").
Here's what this might look like, in a better world:
doThingOne()
.then(doThingTwo)
.then(doThingThree)
.then(launch);
Assuming that doThingOne returns a promise.
A more familiar looking interface for people who use jQuery (or most other promise-using large libraries), might look like this:
var imageLoader = $.Deferred(),
loading = imageLoader.promise();
loading
.done(gallery.render.bind(gallery))
.done(gallery.show.bind(gallery));
var img = new Image(),
url = "...";
img.onload = function () { imageLoader.resolve(img); };
img.onerror = function () { imageLoader.reject("error message"); };
img.src = url;
Very basically, the Deferred above will hold two private arrays (one for "success", one for "failure"), and will extend an interface which allows the async part of the application to "succeed" or "fail", and will pass in whatever is chosen to be data/a callback/etc.
It also extends a promise method, which returns a promise object, containing subscription functions for the two private arrays. So you pass the promise object around to interested parties, and they subscribe callbacks to be iterated through, on success/failure of the async operation (and passed anything which is passed to the .resolve/.reject method of the operation).
This might seem like an inversion or extension of just adding a custom-event/listener/etc...
And it is.
The benefit of the abstraction is that the interface is cleaner.
Hiding this stuff inside of object interfaces, and just passing async promise-objects around can make your code look 100% synchronous:
var images = ImageLoader(),
gallery = ImageGallery(),
photo;
photo = images.load("//url.com/image.png"); // assuming `.load` returns a promise object
gallery.show(photo); // just a promise object, but internally,
//`.show` would subscribe a private method to the promise object
And doing things like having three separate async operations, which can arrive in any order, but must all be successful before advancing, then you can have something like this (again jQuery, but doing it by hand is possible, too).
$.when(promise_obj_1, promise_obj_2, promise_obj_3)
.done(nextPhase);
nextPhase, of course, being a callback which you anticipate to be fired if all three promises are successfully completed.
I'd be happy to provide implementation details for a barebones promise system, if you're like me, and don't like using different libraries without first understanding how each piece works on its own, and being able to replicate its functionality, without copying code.
The answer to the first part of your question is to use an object. You're thinking in C which doesn't have iteratable structs so C programmers reach for arrays. In JS objects are iteratable. So you should write it as:
ary = {
foo : 'foo',
bar : 'bar'
}
Or if we look at your second example:
var apis = {
a : new api.ApiObject(),
b : new api.ApiObject(),
c : new api.ApiObject(),
d : new api.ApiObject()
}
Now, as for the second part of your question. Your pseudo recursive code (pseudo because it's not really recursive in the stack sense since it's async) will now work with the apis object above. But you pass the keys instead of the object:
doInitialize( ['a','b','c','d'] );
Obviously, the bit above can be done dynamically by iterating through the apis object. Anyway, in the onSuccess part of the code you assign the result like this:
apis[ary[0]] = args.obj;
Oh, and obviously the objToInit should now be apis[ary[0]].
Now doing this should work as you expect:
apis.a.doCoolStuff();

Categories

Resources