Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript function not returning value

I am calling a function with the following code:

var resultz = nsEditor.updateStringCall(debtID, column2Change, value2Change, 4, 10);

The function that is being called but doesn't return a value

updateStringCall: function(pdebtID, pcolumn2Change, pvalue2Change, pmin, pmax){
    try {
        var resultz2 = 0;
        $.ajax({
            type: "POST",
            url: "Components/MintLibraries.cfc",
            dataType: "json",
            cache: false,
            data: {
                method: 'StringUpdate',
                val2Change: pvalue2Change.trim(),
                debtID: pdebtID,
                column2Change: pcolumn2Change,
                greaterThan: pmin,
                lesserThan: pmax,
                returnFormat: "json"
            },
            success: function(response) {
                resultz2 = 1;
                return resultz2;
            },  //end done
            error: function(jqXHR, textStatus, errorThrown){
                resultz2 = 0;
                return resultz2;
        }); //end ajax call
    } catch (e) {
        resultz2 = 0;
        return resultz2;
    }  //end trycatch
}, // end updateStringCall

This function uses the .ajax to call a coldfusion cfc method StringUpdate:

<cffunction name="StringUpdate" access="remote" output="false" returntype="any" >    
     <cfargument name="val2Change" type="string"  required="true" />
     <cfargument name="debtID"  type="string"  required="true" />
     <cfargument name="column2Change"  type="string"  required="true" />
     <cfargument name="greaterThan"  type="numeric"   required="false" />
     <cfargument name="lesserThan"  type="numeric"  required="false" />
     <cfset var debt2Pass = int(val(arguments.debtID)) />
     <cfset var updQuery = "" />
     <cfset var retValue = 0 />
     <cfset var iVal = 0 /><cfset var valError = '' />
    <cftry>
     
        <cfquery name="updQuery" datasource="#application.datasource#" result="qResults"    >
                Update dmf set #arguments.column2Change# =
                 <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.val2Change#"/>
                 where DebtID = 
                 <cfqueryparam cfsqltype="cf_sql_smallint" value="#arguments.debtID#"/>
        </cfquery> 
        <cfset retValue = 1 />    
     <cfcatch type="Any" >
                <cfset thrown = ThrowCFError(405,'debug',  'Error updating ' &  arguments.DebtID,arguments.val2Change & ', ' &  arguments.debtID & ',' & arguments.column2Change)  />
                  <cfset retValue = 0 />
         </cfcatch>
         </cftry>
    <cfreturn retValue />
</cffunction>

The query runs successfully but the js function doesn't return a value (it shows up as undefined). Even if it gets an error, I would think I have accounted enough for that to at least get a return value.

Ideas?

like image 640
Michael BW Avatar asked Feb 21 '12 20:02

Michael BW


2 Answers

The function is not returning a value because the returns in your method are embedded inside callback functions. They are only returning from those callbacks, not from your main function. Consider, for example, your "success" callback:

success: function(response) {
    resultz2 = 1;
    return resultz2;
}

This return is just returning from the success function... It doesn't bubble up to your updateStringCall function.

The reason it has to work this way is because ajax calls are asynchronous. Your method returns immediately while the request happens in the background. So in order to get the return value, you have to pass in a callback that has access to the value when it's ready, and then call the callback from within the ajax callbacks instead of returning a value.

So change your method definition to this:

// Note I added a "callback" parameter
function(pdebtID, pcolumn2Change, pvalue2Change, pmin, pmax, callback) { ... }

And then in your ajax callbacks, call it instead of returning a value:

success: function(response) {
    resultz2 = 1;
    callback(resultz2);
},
error: function(jqXHR, textStatus, errorThrown) {
    resultz2 = 0;
    callback(resultz2);
});

Finally, pass in a callback when you call this method:

nsEditor.updateStringCall(debtID, column2Change, value2Change, 4, 10, function(resultz) {
    // Do something with resultz
});

One final note, if you are going to have that blanket try/catch in there, you should change that to use the callback also:

catch (e) {
    resultz2 = 0;
    callback(resultz2);
}

But really, I'd recommend just taking that try/catch out altogether. I can't see how that can possibly be helpful here. It will only hide actual problems with code that already has a better structure for error handling. I suspect you just put in there to debug this return problem, but if it was there already, just take it out.

This is the world of event-driven functional programming! It's a very common sort of structure in javascript.

like image 140
Ben Lee Avatar answered Oct 05 '22 21:10

Ben Lee


Ajax calls are asynchronous. You'll have to work with your result from within the success callback of the $.ajax().

like image 20
Jordan Avatar answered Oct 05 '22 20:10

Jordan