I have a page that prompts the user for information and may need to do multiple web service callouts. Each callout needs to do DML when complete, so I'm using Visualforce Remoting to perform those actions first. Once the actions are complete, I need to execute an Apex method to do some more work. This may be more of a JavaScript question, but hopefully someone has the answer.
Right now, the page doesn't wait for all the remoting calls to finish before invoking the action. How can I get it to wait?
My Button:
<apex:commandButton action="{!buildFax}" onclick="checkForCharts(function(){return true});" value="Build Fax" />
My JS (somewhat simplified):
function getChart(client, accession, callback) {
PatientCharts.getPatientChartToSObjectRemote(
'{!theCase.Id}',
client,
accession,
function(result, event){
callback(event);
});
}
function checkForCharts(docallback) {
// Async worker counters
var workers = 0;
function tickWorkers() {
workers--;
if ( workers === 0 ) {
if (docallback)
docallback();
}
}
j$('[id$="patTab"]')
.find('input[type="checkbox"][name$="chart"]:checked').closest('tr')
.each(function() {
var client = j$(this).find('[id$="client"]').text();
var accession = j$(this).find('[id$="accn"]').text();
workers++;
getChart(client, accession, function(eventres) {
tickWorkers();
});
})
Best Answer
The answer is
apex:actionFunction
to generate a JavaScript function bound to an APEX method that can be passed as a JavaScript callback.Let's try to understand, what happens when pressing your button:
Of course, the
onclick
code is executed first. It means invokingcheckForCharts
, that correctly starts the asynchronous workers and returns no value. Then the returned value (in our case nothing, or rather theundefined
constant) is checked:false
, no further actions are executed,action
method is called normally.Thus the method
buildFax
is called immediately after setting up workers, not waiting for evaluation of the callback.After this long introduction, the fix is easy: