This question is rather long, sorry! I think any shortening would make it ambiguous, though…
I have a requirement to wrap many dozens of asynchronous functions into synchronous functions.
The functions are generated “on-the-fly”, in accordance with specifications in a JSON file, by a module I access with Npm.require().
The functions are grouped by entity like this :
{
"user" : ["getUserByName", "foo", "etc"]
, "pet" : ["getPetById", "bar", "etc"]
, "store" : ["getOrderById", "bloo", "etc"]
}
I need to be able to call them like this …
var aPet = {petId : 486635645};
var thePet = asyncProxy.pet.getPetById( aPet, mimeType );
… not like this …
var callbackGetPetById = function(pet) { console.log('pet', thePet); };
syncProxy.pet.getPetById( aPet, mimeType, callbackGetPetById );
To create synchronous functions from the asychronous ones, I run them through Meteor._wrapAsync one at a time, in an outer/inner loop like this :
for (entity in entities) ...
for (method in entityMethods) ...
:
collectedMethods[entity][method] = Meteor._wrapAsync(
function (arguments, headers, success, error) {
syncProxy[entity][method](
arguments
, headers
, function ( theResult ) { success(null, theResult); }
, function ( theError ) { error(null, theError ); }
)
}
);
:
return collectedMethods;
}
I then test one of them with :
Tinytest.add('Get "Fido" :: Try as bulk pre-wrapped function !', function (test) {
var synchronous_functions = collectMethods(swagger, "sync");
var jsonPet = synchronous_functions["pet"]["getPetById"] ( aPet, mimeType );
var pet = JSON.parse(jsonPet.data)
console.log('pet', pet);
test.equal(pet.name, "Fido");
});
Unfortunately, neither of the callback’s are ever referenced. The correct data is written to a log file by the 3rd party module, but my attempted synchronous function returns jsonPet “undefined”.
Meanwhile, there is no problem if I wrap the functions individually like this :
var getPetById = Meteor._wrapAsync(
function (arguments, headers, success, error) {
syncProxy["pet"]["getPetById"](
arguments
, headers
, function ( theResult ) { success(null, theResult); }
, function ( theError ) { error(null, theError ); }
)
}
);
Tinytest.add('Get "Fido" :: Try with Async.wrap()!', function (test) {
var jsonPet = getPetById ( thePet, mimeType );
var pet = JSON.parse(jsonPet.data)
console.log('pet', pet);
test.equal(pet.name, "Fido");
});
Result: pet.name is indeed equal to “Fido”.
Evidently, the success and fail functions are not getting passed in correctly. The 3rd party module dumps to console.log when no success handler is provided and the Travis listing shows that the correct result is obtained, just unavailable since the success handler is not provided correctly.
So … I would like to ask, what is the correct way to make the success handler available to the methods during the process of wrapping them?
- wrapping in a loop is done between lines 162 & 168
- failing tests begin at line 231
- the several tests preceding line 140 show my efforts to ensure I am building on solid ground.