Any Java script experts in the house.

1,364 Views | 21 Replies | Last: 6 yr ago by bco2003
ttu_85
How long do you want to ignore this user?
Having an issue with a returning an object loaded from an AJAX Jquery call using the .done parameter. Before returning the object to the calling function I am able to see the correctly loaded elements. However once shipped back it comes up undefined. I thought it was due to the asych nature of the call. I understand the .done should return a full completed call.

I'll wear maroon for a week if I can get a hand. Sorry the formatting is beat up. texags removes all the formatting. thanks in advance

The call is simply:

pcodeRec = loadPcodeData(currentPcode, pcodeRec);

The function is :

function loadPcodeData(currentPcode, pcodeRec){

var appUrl = get_BaseUrl();
var sendVar = currentPcode + ",pcode_table,prod_pcode";

// var sendVar = "mac,cust_table,cust_name";
var recReturned = "";
var lastRec = 0;
var recProcessed = "";


alert("beginning sendVar = " + sendVar + " appUrl = " + appUrl);

sendVar = "4250ART,pcode_table,prod_pcode"; //test param
$.ajax({
type: 'post',
url: appUrl + "ajax_sebms.php",
data:"q=" + sendVar,

complete: function(sendVar){ // this block displays all sql recs fitting the search
alert("in complete sendVar = " + sendVar);
}
})
.done(function( sendVar ) {
alert("in loadPcodeData sendVar= " + sendVar);
recReturned = sendVar;
lastRec = recReturned.search(">{") + 1; // find the begining of the jason

if (lastRec > 0) { //Last record clean off the junk and get the JSON
recProcessed = recReturned.substr(lastRec);
var pcodeRec = JSON.parse(recProcessed);
if (pcodeRec.prod_pcode == currentPcode) {
alert("prod_pcode = " + pcodeRec.prod_pcode + " currentPcode = " + currentPcode);
return(pcodeRec);
}
else {
alert("Warning the Pcode not found");
pcodeRec.prod_desc = "NF";
}
}
})
.fail(function( ) {
alert( "Sorry, there was a problem!" );
})
}


redd38
How long do you want to ignore this user?
AG
1) I think you're missing a semicolon on the second to last line.

2) does the alert in the done function execute?

3) does the alert in the complete section execute?
ttu_85
How long do you want to ignore this user?
redd38 said:

1) I think you're missing a semicolon on the second to last line.

2) does the alert in the done function execute?

3) does the alert in the complete section execute?
Thank you for the response.

They do. And I should have mentioned that. The alerts in the CALLING function after the pcodeRec = loadPcode...() do not work. pcodeRec comes back undefined AFTER the call to the function.

pcodeRec is declared, pcodeRec = new Object then loaded with dummy elements all in the calling function then passed as an argument. which all work great until it gets returned.

I think its the asynch business but I thought .done would not execute until the ajax/sql call was completed.

I am an old C programmer so I am thinking I have a trashed element blowing the heap eventhough javascript has auto garbage collection. Its driving me nuts. Its probably something so simple I will hate myself

redd38
How long do you want to ignore this user?
AG
Oh, I think I get the issue (although tricky to see with the lack of formatting).

So the .done is trying to return a value from the loadPcodeData() function, right? But that function finishes execution before the .done is called. It doesn't pause execution and wait for the .done.
ttu_85
How long do you want to ignore this user?
redd38 said:

Oh, I think I get the issue (although tricky to see with the lack of formatting).

So the .done is trying to return a value from the loadPcodeData() function, right? But that function finishes execution before the .done is called. It doesn't pause execution and wait for the .done.
Again thanks for your time.

The .done param actually captures the response from the server and stores it over the initial value in sendVar. That content is then further processed and then returned data back to the initial calling function. it is at that point that alerts fail and that pcodeRec vanishes. Its weird.

In loadPcodeData pcodeRec is visible and can be manipulated. its when the pcodeRec object gets home is when it craps out.



redd38
How long do you want to ignore this user?
AG
ttu_85 said:

redd38 said:

Oh, I think I get the issue (although tricky to see with the lack of formatting).

So the .done is trying to return a value from the loadPcodeData() function, right? But that function finishes execution before the .done is called. It doesn't pause execution and wait for the .done.
Again thanks for your time.

The .done param actually captures the response from the server and stores it over the initial value in sendVar. That content is then further processed and then returned data back to the initial calling function. it is at that point that alerts fail and that pcodeRec vanishes. Its weird.

In loadPcodeData pcodeRec is visible and can be manipulated. its when the pcodeRec object gets home is when it craps out.




The content in the .done param isn't getting returned though... because the loadPcodeData function has already ended (and returned nothing) before the .done code runs. The object returned when .done runs just goes away, it's not captured by anything.
ttu_85
How long do you want to ignore this user?
redd38 said:

ttu_85 said:

redd38 said:

Oh, I think I get the issue (although tricky to see with the lack of formatting).

So the .done is trying to return a value from the loadPcodeData() function, right? But that function finishes execution before the .done is called. It doesn't pause execution and wait for the .done.
Again thanks for your time.

The .done param actually captures the response from the server and stores it over the initial value in sendVar. That content is then further processed and then returned data back to the initial calling function. it is at that point that alerts fail and that pcodeRec vanishes. Its weird.

In loadPcodeData pcodeRec is visible and can be manipulated. its when the pcodeRec object gets home is when it craps out.




The content in the .done param isn't getting returned though... because the loadPcodeData function has already ended (and returned nothing) before the .done code runs. The object returned when .done runs just goes away, it's not captured by anything.
Once again thanks.

You are correct that is exactly what is happening. It looks like I have tree options to make this work

1. Write the results of the loaded object to LocalStorage.set in the .done. When I get home open LocalStorage.get and read the results. Have not tested it but it seems like it would be inefficient creating then destroying an object on each search.

2. Treat it as a synchronous operation with UI dead time waiting for the results. Everyone on stack overflow says that sucks and I tend to agree; not that my app here as anything else to do while waiting for this result.

3. Get the friggin call back to work. This is what is driving me nuts. To get this to go I am probably going to have to go with the LocalStorage route until I can get this call back concept to work with my structure. Again any ideas would be appreciated. I owe you one as it is.
redd38
How long do you want to ignore this user?
AG
I've never used this before so I'm not 100% on this (and this probably isn't how I would solve this but I don't know enough about the big picture goal of your script to help rethink this), but I think you should be able to use "async: false" on your ajax call to make it do what you want. (I think you'll have to return from "complete" instead of "done" though).
JDCAG (NOT Colin)
How long do you want to ignore this user?
AG
I believe your problem is that you are treating the overall function as synchronous, but it is an async call.

If you want to get the correct response from the code calling this function, try to add a return before your $.ajax call. This will return a promise to the calling code. In that code, you'll need to handle the promise, which would essentially mean doing another .done()

So if you did loadPCodeData(param, param2).done(function (responseFromDoneOnAjaxCall){ ...}) then you would get the response.

Basically, if you're calling an async function, it doesn't matter how many functions you wrap it in, they're all going to need to work in an async way.

I don't think you need to do any localstorage here - if you're worried about your UX, you'll have to do something to put up a loading indicator (or something along those lines) while the call is processing, but localstorage isn't going to somehow make your UX magically work.
Halibut
How long do you want to ignore this user?
AG
ttu_85 said:

redd38 said:

ttu_85 said:

redd38 said:

Oh, I think I get the issue (although tricky to see with the lack of formatting).

So the .done is trying to return a value from the loadPcodeData() function, right? But that function finishes execution before the .done is called. It doesn't pause execution and wait for the .done.
Again thanks for your time.

The .done param actually captures the response from the server and stores it over the initial value in sendVar. That content is then further processed and then returned data back to the initial calling function. it is at that point that alerts fail and that pcodeRec vanishes. Its weird.

In loadPcodeData pcodeRec is visible and can be manipulated. its when the pcodeRec object gets home is when it craps out.




The content in the .done param isn't getting returned though... because the loadPcodeData function has already ended (and returned nothing) before the .done code runs. The object returned when .done runs just goes away, it's not captured by anything.
Once again thanks.

You are correct that is exactly what is happening. It looks like I have tree options to make this work

1. Write the results of the loaded object to LocalStorage.set in the .done. When I get home open LocalStorage.get and read the results. Have not tested it but it seems like it would be inefficient creating then destroying an object on each search.

2. Treat it as a synchronous operation with UI dead time waiting for the results. Everyone on stack overflow says that sucks and I tend to agree; not that my app here as anything else to do while waiting for this result.

3. Get the friggin call back to work. This is what is driving me nuts. To get this to go I am probably going to have to go with the LocalStorage route until I can get this call back concept to work with my structure. Again any ideas would be appreciated. I owe you one as it is.

It's a bad idea to turn an async operation (like an AJAX request) into a synchronous operation. You're better off implementing your update logic in the callback of the AJAX request. You shouldn't need localstorage to do what you're doing unless you need to persist data across navigation boundaries (like a page refresh, or closing/opening the browser).

The basic idea is something like this:

function onSuccess(data) {
//Update the DOM with the data we got back from the AJAX request.
//Disable activity indicator
}

function onFailure() {
//Update the DOM or alert user that data couldn't be retrieved.
//Disable activity indicator
}

function getData() {
//Enable an activity indicator so the user knows data is loading

$.ajax({
type:'post',
url: <your url>,
data: <your data>
})
.done(function(data) {
onSuccess(data);
})
.fail(function() {
onFailure();
});
}

--------------------

If your success and failure functions match the same parameters that JQuery passes into the done and fail callbacks, then you can do something like this instead:

$.ajax({ ... })
.done(onSuccess)
.fail(onFailure);

---------------------

Alternatively, you might consider a framework like React.JS (https://reactjs.org/). It has a bit of a learning curve, but once you know it, UIs that interact with async operations become really straightforward.
ttu_85
How long do you want to ignore this user?
Thank you all for the responses. I will study your ideas. Pretty new at this so I very much appreciate the pointers.

I will post back the results. Again many thanks !!!
ttu_85
How long do you want to ignore this user?
Ok Im just a tard, a lowly humiliated tech tard .

Here is all the latest relevant code
I just cant get this thing to work, And its all in the call back I am doing something wrong there.
the .done code works exactly as it should with a loaded object.

The first alert executed is the one just below the call so clearly loadPcode is returning BEFORE the .done is executed. my call back at complete is a fail. Examples in stackoverflow show the callback being passed as a function parameter element which doesnt work in my case for obvious reasons


var pcodeRec = new Object(); //** PCODE OBJECTED CREATED
note I also created it as a GLOBAL failed.


// CALLING BLOCK

if (pcodeLen > 6 && descLen == 0) {

loadPcodeData(currentPcode, pcodeRec); ****CALLING CODE

alert("backHome desc = " + pcodeRec.prod_desc); DIES with UNDEFINED
if(pcodeRec.prod_desc == "NF") {
cells[2].innerHTML = "";
}
else {
cells[2].innerHTML = pcodeRec.prod_desc;
cells[3].innerHTML = pcodeRec.prod_price;
}
if (pcodeLen > 11) {
alert("W A R N I N G Pcode not valid. Exceeding length");
}
}
//*************************************************************************

/* ========================================================================== */
function loadPcodeData(currentPcode, callback){ // <-- tried variations

var appUrl = get_BaseUrl();
var sendVar = currentPcode + ",pcode_table,prod_pcode";
var recReturned = ""
var lastRec = 0;
var response = " ";



alert("beginning sendVar = " + sendVar);

$.ajax({
type: 'post',
url: appUrl + "ajax_sebms.php",
data:"q=" + sendVar,

complete: function(response){
recReturned = response.responseText;
alert( "in complete recReturned= " + recReturned);
callback(response); //<---SUSPECTED PROBLEM. HAVE TRIED A NUMBER OF VARIATIONS

// postProcessing(lastRec, pcodeRec); ??previous approach failed
},
})

.done(function( recReturned ) {
lastRec = recReturned.search(">{") + 1; // find the begining of the jason
alert("in done lastRec = " + lastRec + " recReturned " + recReturned); //** WORKS as Expected
if (lastRec > 0) { //Last record clean off the junk and get the JSON

recProcessed = recReturned.substr(lastRec);
var pcodeRec = JSON.parse(recProcessed);

if (pcodeRec.prod_pcode == currentPcode) { // ** This test works

var prodDesc = pcodeRec.prod_desc;

var prodMach = pcodeRec.prod_mach;
var prodPcode = pcodeRec.prod_pcode; *** OBJECT LOADS ALL WORK
var prodPrice = pcodeRec.prod_price;
alert( "in done prod desc " + prodDesc + " mach " + prodMach + " pcode " + prodPcode + " price " + prodPrice);
//** Alert above works proving the object is correctly loaded
return(pcodeRec); // FUMBLE ON the 5 yardline ****FAIL POINT ** FAIL POINT
}
else {
pcodeRec.prod_desc = "NF";
alert("Warning the Pcode not found");
return(pcodeRec); //FUMBLE ON MY 5 yardline ***fail point

}
}
else {
alert("FAIL recReturned = " + recReturned);
}
})

.fail(function( ) {
alert( "Sorry, there was a problem!" );
})
//

}

Hopefully a Guru will see it . Again forgive the formatting.


ttu_85
How long do you want to ignore this user?
Halibut said:


The basic idea is something like this:

function onSuccess(data) {
//Update the DOM with the data we got back from the AJAX request.
//Disable activity indicator
}


function onFailure() {
//Update the DOM or alert user that data couldn't be retrieved.
//Disable activity indicator
}

function getData() {
//Enable an activity indicator so the user knows data is loading

$.ajax({
type:'post',
url: <your url>,
data: <your data>
})
.done(function(data) {
onSuccess(data);
})
.fail(function() {
onFailure();
});
}

--------------------

If your success and failure functions match the same parameters that JQuery passes into the done and fail callbacks, then you can do something like this instead:

$.ajax({ ... })
.done(onSuccess)
.fail(onFailure);

---------------------

Alternatively, you might consider a framework like React.JS (https://reactjs.org/). It has a bit of a learning curve, but once you know it, UIs that interact with async operations become really straightforward.

could you expand on that please
JDCAG (NOT Colin)
How long do you want to ignore this user?
AG
I just looked for a second....

here's a little cleaned up version - not sure it will work, but should be closer (tonight I can dig in more if you still need it)...

https://codepen.io/anon/pen/XzgpyX

Essentially, if you're wanting to use a callback, which is a way to handle the async (good), you're basically passing a function into your other function and saying "Hey, when you're done, please call this function I'm giving you and pass in the final value"...

Hopefully that codepen is a step in the right direction...
ttu_85
How long do you want to ignore this user?
JDCAG (NOT Colin) said:

I just looked for a second....

here's a little cleaned up version - not sure it will work, but should be closer (tonight I can dig in more if you still need it)...

https://codepen.io/anon/pen/XzgpyX

Essentially, if you're wanting to use a callback, which is a way to handle the async (good), you're basically passing a function into your other function and saying "Hey, when you're done, please call this function I'm giving you and pass in the final value"...

Hopefully that codepen is a step in the right direction...
Interesting that is an approach I have not considered. A bit more advanced than where I am but hey it looks very interesting. More study time !! Appreciate it very much !!
Halibut
How long do you want to ignore this user?
AG
Sorry, I got busy yesterday, so didn't see this until now.

Basically, the onSuccess() function is the callback where you should modify your web page with the data you get back from the AJAX request. I'm not sure how well-versed you are in js web development, but when I say "Update the DOM", basically I just mean "make changes to the HTML elements on the page". Showing/hiding an activity indicator is an optional step. Usually it would just be another DOM update to show an animated GIF. But for the purposes of getting your page working, you should ignore that step for now.

So, DOM updates are basically just manipulating/changing the HTML of the page. From your recent posts, it looks like you have some experience of doing this by setting .innerHTML on various elements.

Your onSuccess function then would be something like this:

function onSuccess(serverResponse) {

//Identify the HTML element(s) you want to update
//Example uses document.getElementById(), but there are a lot of ways to do this
var element = document.getElementById('my-element-to-update');

//Update the element with the data from the server
//This example code will replace contents of the element with a single <span> element
//and it expects the serverResponse parameter to have a field called "whatever"
element.innerHTML = "<span>Hey, this is a test. '+serverResponse.whatever+"</span>";

}

---------------

It might be helpful to try to test the callback (the onSuccess function) independently of the AJAX request. Basically, create a hard-coded test response and execute the callback with the test response as the parameter. Here's some code that would invoke the callback after waiting for 3 seconds. You would need to customize the testResponse variable to make it look like something the server would return:

window.setTimeout(function(){

//you need to setup some example data from the server
var testResponse = {
whatever: 'some server data'
}

//execute your callback function
onSuccess(testResponse); //invoke your callback with the test data

}, 3000);

--------------

If you could post all of the relevant code you're working with (HTML and javascript), and an example of the response you expect from the server, I might be able to help you more later this evening.

ttu_85
How long do you want to ignore this user?
Halibut said:

Sorry, I got busy yesterday, so didn't see this until now.

Basically, the onSuccess() function is the callback where you should modify your web page with the data you get back from the AJAX request. I'm not sure how well-versed you are in js web development, but when I say "Update the DOM", basically I just mean "make changes to the HTML elements on the page". Showing/hiding an activity indicator is an optional step. Usually it would just be another DOM update to show an animated GIF. But for the purposes of getting your page working, you should ignore that step for now.

So, DOM updates are basically just manipulating/changing the HTML of the page. From your recent posts, it looks like you have some experience of doing this by setting .innerHTML on various elements.

Your onSuccess function then would be something like this:

function onSuccess(serverResponse) {

//Identify the HTML element(s) you want to update
//Example uses document.getElementById(), but there are a lot of ways to do this
var element = document.getElementById('my-element-to-update');

//Update the element with the data from the server
//This example code will replace contents of the element with a single <span> element
//and it expects the serverResponse parameter to have a field called "whatever"
element.innerHTML = "<span>Hey, this is a test. '+serverResponse.whatever+"</span>";

}

---------------

It might be helpful to try to test the callback (the onSuccess function) independently of the AJAX request. Basically, create a hard-coded test response and execute the callback with the test response as the parameter. Here's some code that would invoke the callback after waiting for 3 seconds. You would need to customize the testResponse variable to make it look like something the server would return:

window.setTimeout(function(){

//you need to setup some example data from the server
var testResponse = {
whatever: 'some server data'
}

//execute your callback function
onSuccess(testResponse); //invoke your callback with the test data

}, 3000);

--------------

If you could post all of the relevant code you're working with (HTML and javascript), and an example of the response you expect from the server, I might be able to help you more later this evening.


Good evening. I did not get a chance to work on this today. Tomorrow is another matter. I will give your suggestions here a try. Thank you for helping me out.

For now, I know blasphemy, I am using localstorage. setItem .getitem. and .removeItem as a work around. It actually works so I can continue dev in other areas of the browser based application. examples:

saving the loaded object after its retrieval from php-> sql:
localStorage.setItem('pcodeRec', JSON.stringify(pcodeRec));
//----------------------------------------------------------------------------------------------//
retrieving and reloading the object:
loadPcodeData(currentPcode, pcodeRec); //**Calling line

var retrievedObject = localStorage.getItem('pcodeRec'); //Jury rigged solution until the call back issue is solved
pcodeRec = JSON.parse(retrievedObject); // reload the Object

This is part of a browser based small business management system and in particular the invoice part or product code table look up system. Its nothing top secrete by any means but does have some stuff I would rather not show but I would be happy to provide all relevant code.

I am new to javaScrpt/php but not programming. I used to do a bunch C and Oracle work back in the day and was a Systems Analyst. I ran/owned another business for 23 years and I am attempting to get back into dev work as an experienced old guy. Thought I better have something to show perspective clients or possibly employers. Given this you may find my work an odd a blend of rookie and experienced.

Again thanks for getting back to me. And apologies for the delayed replay.

BTW rather interesting discussions on stackoverflow regarding the localStorage approach regarding performance given there is reduced waiting for the async wait. I am far from qualified to know. But like lots of other IT tools and concepts it seems to be debated.
ttu_85
How long do you want to ignore this user?
JDCAG (NOT Colin) said:

I just looked for a second....

here's a little cleaned up version - not sure it will work, but should be closer (tonight I can dig in more if you still need it)...

https://codepen.io/anon/pen/XzgpyX

Essentially, if you're wanting to use a callback, which is a way to handle the async (good), you're basically passing a function into your other function and saying "Hey, when you're done, please call this function I'm giving you and pass in the final value"...

Hopefully that codepen is a step in the right direction...
Thanks for this. One thing I find very confusing about JS are these inline functions in bold. I am not going to pretend I have a solid understanding here but i see you are using function(finalPcode) as an argument to loadPcodeData() along with the pcode Object. I understand functions as argument but this implementation not so much So callback is the receiving element in the constructor ??

I did try this and it did "compile"/run but also came back with the element undefined. I cut it from your codepen you were kind enough to provide. Thanks for that. It is very possible that I jacked up the implementation. I did try several variations.

loadPcodeData(currentPcode, function(finalPcode) {
alert("backHome desc = " + finalPcode.prod_desc);
if(finalPcode.prod_desc == "NF") {
cells[2].innerHTML = "";
}
else {
cells[2].innerHTML = finalPcode.prod_desc;
cells[3].innerHTML = finalPcode.prod_price;
}

if (pcodeLen > 11) {
alert("W A R N I N G Pcode not valid. Exceeding length");
}
//*************************************************************************
})




JDCAG (NOT Colin)
How long do you want to ignore this user?
AG
Let me explain a bit of how that works.

So you know how a function works:

==========================

function someFunction(name, age) {
console.log('Hello ' + name + '. You are ' + age + ' years old.');
}

someFunction('Sammy', 24);

==========================

Okay, so now keep in mind that when you call a function, whatever you pass in is what fills in the parameters (you know this on basic functions like above - 'Sammy' becomes "name" in the function, 24 becomes "age".)

So now, we have something like this (NOTE: this is just an example - there is no async behavior here, so no REASON for a callback)...

==================

function someFunction(name, age, callback) {
var outputString = 'Hello ' + name + '. You are ' + age + ' years old.';
callback(outputString);
}

someFunction('Sammy', 24, function(output) {
console.log(output);
});

========

All that is happening above is that we're passing in a function, which then gets assigned to "callback" in the someFunction definition. Instead of outputting the text itself, it bundles it up and just passes it to the callback. This is the same thing you've seen before - the only difference is that it is anonymous, so you have to realize that "callback" is just another name for that function that was passed in. So when you pass it that outputString variable, it means that text is what gets put in "output" in the anonymous function.

Callbacks are just a way to handle async (or potentially async) calls because they say "Hey, I know you won't have an answer right away, so instead of expecting you to respond with the answer, I'm going to give you a function and ask that you call it and pass it the response once you've figured it out".

Another way to handle async behavior is promises, but they're much more complicated and confusing for folks just diving in (there are a few different implementation standards, but that is what is happening when you see code that has .then()/.catch() or .done()/.fail() tacked on to the end. It's the same idea - do what you're doing, then when it is done the promise calls the .done or .then or whatever implementation you're using.

JDCAG (NOT Colin)
How long do you want to ignore this user?
AG
I will say that on codepen, I just pulled it over, but there are some things that aren't going to work right -

1. At the top, you're referencing pcodeLen & descLen but neither have been defined.
2. cells aren't defined anywhere - in fact, there is no DOM at all

These are most likely just issues caused by the fact you're pulling it from a bigger piece of code.
ttu_85
How long do you want to ignore this user?
JDCAG (NOT Colin) said:

I will say that on codepen, I just pulled it over, but there are some things that aren't going to work right -

1. At the top, you're referencing pcodeLen & descLen but neither have been defined.
2. cells aren't defined anywhere - in fact, there is no DOM at all

These are most likely just issues caused by the fact you're pulling it from a bigger piece of code.
Yes this is true. This code is part of a larger function. loadPcodeData is called from here. And thanks for your help and examples. I now have it working great.

Really appreciate you, red, and Halbit weighing in.
JDCAG (NOT Colin)
How long do you want to ignore this user?
AG
Awesome! Glad to help.
bco2003
How long do you want to ignore this user?
AG
ttu_85 said:

I'll wear maroon for a week if I can get a hand.


Wear that maroon proudly.
Refresh
Page 1 of 1
 
×
subscribe Verify your student status
See Subscription Benefits
Trial only available to users who have never subscribed or participated in a previous trial.