I’m running an ajax request. I am sending data to PHP and then retrieving the data back. This works with the below jQuery. However, I am trying to now pass the jQuery ajax response to update a global variable in my JS (not jQuery) so that I can use the variable as needed.
I have learned about callback functions but can’t seem to figure out how to implement them. Here’s the code.
(function (d) {
var jsonobjvar; // < -- stays undefined
jQuery(document).ready(function ($) {
var data = {
'url': 'ajax.php',
'action': 'my_other_action', // arbitrary
'whatever_other': name // arbitrary
};
// making a response alert with the data
jQuery.post(data.url, data, function (response) {
var jsonobj = $.parseJSON(response);
alert('Got this from the server: ' + response);
jsonobjvar = response;
jsonobjvar;
};
});
});
})(document);
I can assign the response into a different variable, but when I try to update the global variable it keeps saying undefined. I’ve even tried setting a timer.
Thanks in advance! Sorry new to JS, even newer to jQuery. Preferred not to use it but couldn’t seem to find a way to make ajax requests with javascript.
You don’t need jQuery to make http request. Use the proprietary modern browser fetch api instead. You need to wait to use that variable until the http request comes back. You can do that by using await with fetch to stall and stop javascript until the async request is received.
fyi modern javascript dev does away with jquery completely taking its place ~somewhat are mvvm (model-view-view-model) ui frameworks which are Angular, React, and Vue to name the top contenders. Each of those projects share the pursuit of optimization and simplification of displaying dynamic content obtained through async means like a http request.
The only place you will really come across jquery is in older legacy code and monolithic cms platforms like WordPress. The rest of the modern ui dev world has moved on. The many advantages of jQuery have been negated by innovation of modern browsers and standardization of apis.
This is a pretty good article detailing the inevitable demise of jQuery.
https://love2dev.com/blog/jquery-obsolete/
Hi,
The problem here is that Ajax requests are asynchronous (the clue is in the name — Ajax stands for “Asynchronous JavaScript and XML”). This means that your code doesn’t wait for the request to complete before (for example) logging the value of the global variable somewhere else in your code.
Have a look at this article to understand more:
jQuery is JavaScript and as @windbeneathmywings says, it is becoming less and less relevant as modern browsers implement many of its features natively. I wouldn’t go as far as to say “Don’t use it”, if it works for you, but if you’re not invested in it already, it might be worth learning how to do things without (in this case via the FetchAPI).
Have a read of the article I posted, as well as the two MDN articles posted by windbeneathmywings and let us know if you have any questions.
@James_Hibbard @windbeneathmywings - thanks for your input. I spent close to a week trying to truly understand ajax using jQuery because @James_Hibbard suggested I look into wp_ajax. So from the article here ajax it list instructions on implementing this.
Anyways, totally willing to try and use JS as I would prefer this.
I am trying to accomplish the same with JS but keeps throwing an error message
A cross-origin resource sharing (CORS) request was blocked because it contained request headers that were neither CORS-safelisted ( Accept
, Accept-Language
, Content-Language
, Content-Type
) nor allowed by the Access-Control-Allow-Headers
response header of the associated preflight request.
Here;s the code.
var url = '/admin-ajax.php';
fetch(url, {
method: "post",
credentials: 'same-origin',
headers: new Headers({ 'Content-Type': 'application/json' }),
body: "action=my_other_action",
whatever_other: name
})
.then(res => res.json())
.then(data => console.log(data))
.catch(error => console.log("did not work"));
Can you guys spot the error? Also, does async-await make the entire page not load?
Cors error on the same domain would indicate an error on the server inside admin-ajax.php.
1 Like
Added
mode: ‘no-cors’
And I get a response.
Now, I have to figure out how to get data from the server, and then be able to update the global variable.
Use await in front of fetch and assign the result to the variable. Await will stop the program, wait for the async response and once recieved assign the value to the variable and continue the program.
From dev tools Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules
Move your script into a separate file with .mjs extension and use script tag in html file to load it.
Appears you can also do this instead of a separate file.
<script type="module">
/* JavaScript module code here */
</script>
This is inside a JS file already. Also, I tried adding async to the front of the first fetch and also tried creating a function for the result and adding it in front of the function. Do I really need to add script tags to a JS file or perhaps my code syntax is incorrect?
fetch(url, {
method: "post",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
mode: 'no-cors',
//make sure to serialize your JSON body
body: JSON.stringify({
name: myName,
password: myPassword
})
})
// .then((response) => {
async function fetchIt(resource) {
const fetchResult = await fetch(resource);
alert(fetchResult);
}
I confess out of my depth when it comes to networks, but this sounds to me like the root of the problem.
If you go back to your original implementation before async/await what do you find in the devtools under the network tab. You will probably want to click on admin-ajax.php in the list.
To give you an idea, I have just tried the two following approaches remotely on my website’s server and both are working.
fetch
const setData = async (url, data) => {
try {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
if (response.ok) return await response.json()
throw Error(`${response.url}: ${response.status} ${response.statusText}`)
} catch (err) { console.log(err) }
return {}
}
...
async function addButtonHandler (event) {
const props = { ... }
const propsFromResponse = await setData('./set-data.php', props)
addElements.addButton(propsFromResponse)
buttonId++
}
jQuery ajax
const setData = function (url, data) {
return jQuery.ajax({
url,
data: JSON.stringify(data),
dataType: 'json',
method: 'POST'
})
}
function addButtonHandler (event) {
const props = { ... }
const response = setData('./set-data.php', props)
response
.then(function (props) {
addElements.addButton(props)
buttonId++
})
.catch(console.log)
}
edit: the set-data.php test file
<?php
$element = json_decode(file_get_contents('php://input'), true);
$element['textContent'] = 'From Server: ' . $element['textContent'];
header('Content-Type: application/json');
echo json_encode($element);
Personally I agree modules, async/await is the way to go, but I think you might be better off ironing out this network issue first.
Have you tested the php code outside of JavaScript to verify that it works. If not a simple tool other than the command line to do so is postman.
https://www.postman.com/
There is also a lighter weight alternative for vscode.
When building apps that communicate with apis always test the api outside the app to verify it does what is expected. Once verified integrate into the app.
I pulled the PHP code directly from the codex site. It also works with jQuery ajax.
I didn’t expect a different solution to be proposed e.g. instead of jQuery ajax use fetch.
So with Fetch, I am attempting to get duplicate what I did with jQuery. Having an issue grabbing the data from the PHP file which has access to the database though. Switching from jQuery to fetch has put me one step behind. (which is fine, I prefer using JS).
Basically, my PHP file grabs data from the database and I need to echo that data back into the response. This was working with the jQuery solution above.
Lastly, once the data has been sent back to the fetch function response, it then needs to be stored in a Global variable so that it can be used to manipulate the DOM with javascript.
Right, a voyage of discovery 
action
First of all with regards sending an action to be called in php, could you not just add it to your data? e.g
const setData = async (url, data) => {
try {
const response = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ...data, action: 'addPrefix' }) // adding an action here
})
if (response.ok) return await response.json()
throw Error(`${response.url}: ${response.status} ${response.statusText}`)
} catch (err) { console.log(err) }
return {}
}
You can then call that in php with the appropriate function e.g.
add_action( string $hook_name, $my_data['action'])
I tested this with call_user_func_array
<?php
function addPrefix(&$elem, $prefix) {
$elem['textContent'] = $prefix . $elem['textContent'];
}
$element = json_decode(file_get_contents('php://input'), true);
$callback = $element['action']; // get the name of the function in string format
call_user_func_array($callback, array(&$element, 'From Server: '));
header('Content-Type: application/json');
echo json_encode($element);
sending back a response
I would suggest you have a read through the json_encode page.
If you are sending back a single variable it would really need be associated with a key to make a valid json object. I would imagine something like this.
$my_var = 'This is a test';
echo json_encode(array('data' => $my_var));
// {"data":"This is a test"}
2 Likes
jQuery will also do a couple of things for you under the hood, such as send along any relevant cookies to the server. This could well be why one implementation is working and the other isn’t.
It is definitely a great learning exercise to convert jQuery to using the FetchAPI, but if you have a (potentially time critical) task to complete, then I wouldn’t worry too much about the FetchAPI.
While jQuery is definitely nowhere near as necessary as it was 10 years ago, it still powers a huge number of websites (amazon.com, for example, as I found out today).
2 Likes
Yeah, hopefully in the long run switching from jQuery ajax to JS fetch will be worth it. Kind of dedicated the entire weekend to this. For something in a year would probably take 15 minutes. Lol
Perhaps some people don’t care about using jQuery, some JS, etc. It seems it would be better to have the least amount of library dependencies possible for any program. Perhaps it doesn’t matter though.
It’s a noble notion but real world applications are much more than tiny code snippets like this. Reducing duplication across multiple apps like most companies have requires sharing code as dependencies. Furthermore, efficiently developing solutions to business problems requires acknowledging and learning to utilize tools already available in any in given ecosystem. Writing things from scratch is good for learning but not for building large scale maintainable software solutions within a team environment. As a professional developer you will thrown into existing projects and architectural methodologies which you will be expected to follow and not reinvent wheels. A good way to get a taste of professional dev is to contribute to an existing open source project. Find an issue and see it through to being committed to the source code. In that process you will discover everything that goes on in professional development.
2 Likes
Totally get that. For me once I understand what something can do, and the syntax, then it hopefully starts clicking. That’s what happened with CSS. It literally seemed like overnight I figured it out, once I understood what you can do with it and how to write it.
Hoping that is how JS will pan out as well. But that makes sense what you shared and thank you for sharing it.
Figured it out. All that was needed was to save the response into a variable as you normally would. Then call a new function from within the response data function. The new function can update the variable. It appears the reason this works is because the new function is only called after the response ajax request is finished so it can actually store the variable.
var jsonobjvar;
jQuery(document).ready(function ($) {
var data = {
'url': 'ajax.php',
'action': 'my_other_action', // arbitrary
'whatever_other': name // arbitrary
};
jQuery.post(data.url, data, function (response) {
jsonobjvar = response;
saveTheVarResponse();
};
});
});
function savetheVarResponse() {
jsonobjvar;
}
@rpg_digital Did it!
Yes, that is the purpose of the success
callback function.
Here’s the jQuery.post() documentation.
What that documentation says about the success function is: " A callback function that is executed if the request succeeds. Required if dataType
is provided, but can be null
in that case."
Or in other words, when the data is sent to the server and a response is sent back from that server, the success function is used to help you process that response.