Reputation: 65
I've defined this function:
// retrieves zip of package manifest supplied
var retrieveZip = function(metadataClient, args, callback) {
metadataClient.retrieve(args, function(err, result) {
metadataClient.checkRetrieveStatus({id: result.result.id, includeZip: 'true'}, function(err, result) {
if(result.result.done) {
return callback(result);
}
// else check again!(how??)
});
});
}
retrieveZip(metadataClient, args, function(result) {
console.log(result);
});
The idea is that the client will attempt to retrieve a zip file based on the metadata supplied in args. The API documentation (Salesforce SOAP API) requires the id supplied in the result of the retrieve method to be passed into a check status function.
However the problem is this:
On the first check, if the result is 'done' then just return to the callback the result object from checkRetreiveStatus
(contains the result)
BUT if the result isn't done, I need to call checkRetrieveStatus
again... from inside checkRetrieveStatus
The naive approach would be to pass the parameters from the original checkRetrieveStatus
call into a new instance of checkRetrieveStatus
but obviously it's impossible to know how many times this would be invoked.
It sounds like I need a recursive solution to this? Would using a while-loop would introduce problems with asynchronous calls?
Upvotes: 1
Views: 1543
Reputation: 101662
From your description, it sounds like you just want to call checkRetrieveStatus
until it's done, not retrieve
and checkRetrieveStatus
. Is that correct?
If so, the thing to do is to extract the status check out into your own function that can recursively call itself, like this:
var checkStatus = function(metadataClient, id, callback) {
metadataClient.checkRetrieveStatus({ id: id, includeZip: 'true' }, function(err, result) {
if (result.result.done) {
callback(result);
} else {
checkStatus(metadataClient, id, callback);
}
});
};
var retrieveZip = function(metadataClient, args, callback) {
metadataClient.retrieve(args, function(err, result) {
checkStatus(metadataClient, result.result.id, callback);
});
}
retrieveZip(metadataClient, args, function(result) {
console.log(result);
});
And if you're worried about hogging system resources while it repeatedly polls the result, you can include a delay between checks:
var checkStatus = function(metadataClient, id, callback) {
metadataClient.checkRetrieveStatus({ id: id, includeZip: 'true' }, function(err, result) {
if (result.result.done) {
callback(result);
} else {
setTimeout(function () {
checkStatus(metadataClient, id, callback);
}, 100);
}
});
};
var retrieveZip = function(metadataClient, args, callback) {
metadataClient.retrieve(args, function(err, result) {
checkStatus(metadataClient, result.result.id, callback);
});
}
retrieveZip(metadataClient, args, function(result) {
console.log(result);
});
Upvotes: 2
Reputation: 1563
Better to split the function so you do not have to re-enter the top.something like this (did not try to run this, so just get the idea)
// retrieves zip of package manifest supplied
var retrieveZip = function(metadataClient, args, callback) {
metadataClient.retrieve(args, function(err, result) {
doCheck(result,function(res){
callback(res)
})
});
}
function doCheck(result,cb){
metadataClient.checkRetrieveStatus({id: result.id, includeZip: 'true'}, function(err, innerResult) {
if(result.result.done) {
return cb(result);
}else{
doCheck( innerResult ,cb)
}
});
}
retrieveZip(metadataClient, args, function(result) {
console.log(result);
});
Upvotes: 0