3

Using JS REST toolkit, I'm trying to insert one customer record and multiple related contact records, and then redirect to the detail page of the customer record via JS. The problem is JS redirects before the async calls are complete, and I can't place the redirect in the callback because there are multiple record inserts.

My JS:

function saveCustomer() {
    // ... saves customer using client.create()
    // callback calls saveContacts passing record id: saveContacts(response.id)
    // ...
}

function saveContacts(customerId) {
    $('.row').each(function() {
        saveContact($(this));          // sends each row
    });
    var url = "apex/accounts?id=" + customerId;    // This should be wait until .each
    window.location=url;                           // and async calls are finished.
}

function saveContact($row) {
    var client = new remotetk.Client();
    client.create("Contact__c", {   Name: $row.find('.name').val(), 
                                    Age: $row.find('.age').val(), 
                                    Address: $row.find('.address').val(), 
                                    City: $row.find('.city').val(), 
                                    State: $row.find('.state').val(), 
                                    Zip: $row.find('.zip').val()
                                },
    function(response) {
        console.log('Success!');
        console.log(response);
    },  
    function(error) {
        console.log('Error!');
        console.log(error);
    });
}

Relevant section of RemoteTK.component:

function handleResult(result, callback, error, nullok) {
    if (result) {
        result = JSON.parse(result);
        if ( Array.isArray(result) && result[0].message && result[0].errorCode ) {
            if ( typeof error === 'function' ) {
                error(result);
            }
        } else {
            callback(result);
        }
    } else if (typeof nullok !== 'undefined' && nullok) {
        callback();
    } else {
        error([{ message : "Null return from action method","errorCode":"NULL_RETURN"}]);
    }        
}



remotetk.Client.prototype.create = function(objtype, fields, callback, error) {
    Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.RemoteTKController.create}', objtype, JSON.stringify(fields), function(result){
        handleResult(result, callback, error);
    }, { 
        escape: false
    });
}

Note that the user can add or remove rows at any time before clicking "Save".

1

You should solve this by using jquery.when. This method will wait until all callbacks are done.

sample:

var actions = [];
$('.row').each(function() {
    var that = this; //keep static reference
    actions.push(function(){saveContact($(that));});  
});

$.when.apply($,actions).done(function(){
  //check results if you want on "arguments"
  var url = "apex/accounts?id=" + customerId;   
  window.location=url;  
});

Probably you would need to change the default callback to mark as done. If changing saveContact to return client doesn't work.

You will find many deferred/wait samples on stackoverflow to clarify.

Since forcetk is using jquery other option is to set jquery.ajax as a syncronic method by:

jQuery.ajax({ async: false,....});
  • Thanks Martin. I'm struggling with this. saveContact definitely can't return client, so how can you change the callback to mark as done? The redirect still occurs before the response because of the disconnect. – geeljire Jun 6 '13 at 17:15
  • You have a good sample there about how to use deferred (and promise) stackoverflow.com/questions/5436327/… – Martin Borthiry Jun 6 '13 at 18:27

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.