3

I'm using an offline application's javascript API and I'd like to know if I can use deferred objects to handle the callbacks. The API calls do not use HTTP, the calls are to and from the applications local database.

The only way I've been able to display information is by using 'setTimeout' on subsequent calls, which I know, is terrible! So I have a long list of callbacks and timeouts.

var jsObj = {};
var anotherObj = {};

//first async call
methodName("arg1", jsObj, callback);

function callback(result){

  jsObj["data"] = result;

}

//second async call
setTimeout(function(){methodName("arg1", anotherObj, callback2);}, 200);

function callback2(result){

  jsObj["data"] = result;

}

//wait
setTimeout(function(){

  $("#content").html(JSON.stringify(jsObj));

},300);

Is there anyway to refactor this? Any advice is appreciated. I've looked at the following post, but I'm not sure it would work. I'm aware I can create custom deferred objects (jQuery), but altering the API to use this or any other method of promise objects seems unrealistic.

  • This is not an official answer or anything, but I think I had the same problem doing some TDD using Q. I think the issue is that the function returns too quickly. I was about to start throwing timeouts in there but just decided to go ahead an make the filesystem calls. – ipaul May 21 '14 at 17:43
0

Deferred objects are indeed the way to go here. You don't have to change the API, just use a promise library like Q that can wrap it. It would look something like this:

promiseMethodName = Q.denodeify(methodName);

promiseMethodName("arg1", jsObj).then(function(result) {
  jsObj["data"] = result;
  return result;
}).then(function(result) {
  return promiseMethodName("arg1", anotherObj);
}).then(function(result) {
  jsObj["data"] = result;
  return result;
}).then(function(result) {
  $("#content").html(JSON.stringify(jsObj));
});

If your API doesn't use node-style callbacks, you might need to implement your own version of denodeify, which can be tricky, but the rest will be the same.

  • I'm not able to avoid the third argument in the method being the name of a callback. The calls won't return anything if I take it out. I assume this is where I'd have to override denodeify's default behavior? – Mike May 21 '14 at 20:00
  • denodeify expects the last argument to be a callback. The whole point of denodeify is to return a new function that gets rid of that last argument and uses a promise instead. The signature of the callback is function(err, result) though. If your callbacks don't have the err parameter, that's when you have to implement your own denodeify. – Karl Bielefeldt May 21 '14 at 20:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.