There are about a million posts on SO about async callbacks, but I cannot figure out how to get mine to work
I have an AJAX request:
function checkName();
var ajax = new XMLHttpRequest();
ajax.open("POST", "index.php", true); // true = async
ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
ajax.onreadystatechange = function(){
if(ajax.readyState == 4 && ajax.status == 200){
var pass = ajax.responseText + 0;
}
}
ajax.send("emailcheck="+email);
return pass;
}
The only possible outcomes for pass are 1 or 0.
I've tried moving the return immediately after the assignment of pass, but still nothing. That's when I started looking around on here and found callbacks, but I'm having trouble figuring out how to do it.
What I would like to do is have something like:
if(checkName()){
// Do stuff
}else{}
I don't want to do a synchronous ajax request (i.e. false for third param), because that stops an animation I have and also prevents the user from performing other tasks on the site for the short time the call takes place.
I know this is very similar to other posts about the topic, I just can't quite figure it out.
Thank you in advance.
Only with a synchronous call you can implement this. And no one would want that. You said it yourself.
if(checkName()){
// Do stuff
}else{}
You need to use a callback function indeed. See this example:
function checkName(callBack) {
var ajax = new XMLHttpRequest();
ajax.open("POST", "index.php", true); // true = async
if (callBack)
{
ajax.callBack = callBack;
}
ajax.onreadystatechange = function(){
if(this.readyState == 4 && this.status == 200){
if (this.callBack)
{
this.callBack(this.responseText);
}
}
}
ajax.send("emailcheck="+email);
}
function checkNameFinish(data)
{
alert(data);
}
checkName(checkNameFinish);
checkName now accepts an argument callBack. This has to be a function. When the readystate completes it checks if there's a callBack set. If so then execute the callBack function and pass the response as argument.
Related
I want to execute a function (named callback in this context) with a weblistener in Javascript. When the listener detect the good pattern it calls the callback function and this function never stop...
All of this is done with browser.webRequest.onBeforeRequest.addListener
The weblistener with browser.webRequest.onBeforeRequest.addListener() detects the good pattern, call the associated function which make a GET request. Once it's done, the GET request is done again and again
function getResponseFromSP()
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200){
console.log(xmlHttp.response);
browser.webRequest.onBeforeRequest.removeListener(getResponseFromSP);
if(!browser.webRequest.onBeforeRequest.hasListener(getResponseFromSP)){
browser.webRequest.onBeforeRequest.addListener(
getResponseFromSP,
{urls: ["https://example.com/policy"]}
);
}
}
}
xmlHttp.open("GET", "https://example.com:5000/policy", true); // true for asynchronous
xmlHttp.responseType = 'json';
xmlHttp.send(null);
}
/*
Main part
*/
browser.webRequest.onBeforeRequest.addListener(
getResponseFromSP,
{urls: ["https://example.com/policy"]}
);
One common solution is to create a variable in the appropriate scope, check that it's false when you want to execute the function, but set it to true after execution.
var isDone = false;
// ...
if(!isDone) {
// ... execute the function on the event being listened for here, then set
isDone = true;
}
Hello I've been trying to wrap my head around returning data from a XMLHttpRequest Function. I've tried many different ways but the only thing i can get when i try to output the data to a console from out-side the function i always get 'undefined'. it only works if i do it from inside the function itself.
<script>
var object;
function loadJSON(path, success, error) {
var xhr = new XMLHttpRequest();
var obj1;
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
if (success)
success(JSON.parse(xhr.responseText));
//console.log(data); works here!
} else {
if (error)
error(xhr);
}
}
};
xhr.open("GET", path, true);
xhr.send();
}
object = loadJSON('jconfig.json',
function (data) { console.log(data); return($data);/*works here! but does not return!*/ },
function (xhr) { console.error(xhr); }
);
console.log(object);//does not work here
</script>
I know this is a very simple problem but I've been stuck with this problem for over an hour now and the answers given on other similar questions cant seem to get me over this obstacle. Any help is highly appreciated!
EDIT: I updated the code with some suggestions but i still cant get ti to work. Any suggestions to get the code above to finally return something i can use outside of the functions.
The line console.log(object) is executed just after the laodJSON() function is called and the JSON object isn't loaded till then.
This is related to callbacks and async functions. Your loadJSON() can only actually load the JSON when it get's response from the server.
Instead, if you want to call the JSON object outside the loadJSON() function, you need to use a callback function. Something like this:
<script>
var object;
function loadJSON(path, callback) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
// Here the callback gets implemented
object = JSON.parse(xhr.responseText);
callback();
} else {
}
}
};
xhr.open("GET", path, true);
xhr.send();
return xhr.onreadystatechange();
}
loadJSON('jconfig.json', function printJSONObject(){
console.log(object);
});
// this will not work unless you get the response
console.log(object);
</script>
Update: "Returning" a value from an async function by the use of callbacks is pointless, since the next line of code will be executed immediately without waiting for the response.
Instead, if you want to use the object outside of the function sending an XHR request, implement everything inside your callback function.
Hey guys I'm running an IIFE and an ajax call and it seems to not respond at all...
var $ = {
core:function(u){
return new $.httpRequest(u);
},
httpRequest:function(url){
var text;
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (this.readyState != 4 || this.status != 200) return;
text = this.responseText;
};
r.send();
console.log(text);
return text;
}
};
Is there something silly I am missing? Just been over this a few times and I have my hands full and hope that our savvy SO members could help out. Should I place the return inside the onload?
The onreadystatechange function you assign is where you need to handle the responseText. You need to either process it there or call some function and pass it the data. Remember, the ajax call is asynchronous which means that you start it with your r.send(), your $.httpRequest() function finishes, your other javascript after it executes and then some time later the ajax call completes and calls your onreadystatechange function. At that point, all you can do is to either process the data right there in that function or call some other function and pass the data to it.
Here's one way of doing it using a callback function that you pass into your httpRequest function:
var $ = {
core:function(u){
return new $.httpRequest(u);
},
httpRequest:function(url, callback){
var r = new XMLHttpRequest();
r.open("GET", url, true);
r.onreadystatechange = function () {
if (r.readyState != 4 || r.status != 200) return;
callback(r.responseText);
};
r.send();
}
};
Example usage:
$.httpRequest("http://examplesite.com/myurl", function(data) {
// write code here to process the data
});
I have this problem.
I have a function for example called functionA() that needs the results from another function called functionB().
var globalVar="";
function functionA(){
//...
functionB();
//here i have to use the global variable (that is empty because functionB isn't finished)
}
function functionB(){
//ajax request
globalVar=ajaxRequest.responseText;
}
How can I do to let the functionB finish befor continue with the execution of functionA?
Thanks!
This is the code:
var ingredientiEsistenti="";
function ShowInserisciCommerciale() {
getElementiEsistenti();
JSON.parse(ingredientiEsistenti);
}
function getElementiEsistenti(){
// prendo gli ingredienti esistenti.
var url = "http://127.0.0.1:8080/Tesi/Ingredienti";
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", url, false);
xmlHttp.send(null);
xmlHttp.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) // COMPLETED
{
if (xmlHttp.status == 200) // SUCCESSFUL
{
ingredientiEsistenti = xmlHttp.responseText;
} else {
alert("An error occurred while communicating with login server.");
}
}
};
}
You've got one of many options, that don't require an evil global variable:
Move the code you want to see executed to the onreadystatechange callback of the ajax request, that way, it won't get executed until you received a response
Redefine functionA, so that it takes a parameter that allows you to skip the first bit:
Make the request synchronous, not recommended, though
use a timeout/interval to check the readystate of the request manually (brute-force, not recommended either)
Perhaps there is some worker trickery that could do the trick, too, in your particular case
function functionA(skipDown)
{
skipDown = skipDown || false;
if (skipDown === false)
{
//doStuff
return functionB();//<-- call functionA(true); from the readystatechange callback
}
//this code will only be called if skipDown was passed
}
It is impossible to have a sleep/wait in JavaScript when the call is asynchronous. You need to use a callback pattern to make this action occur.
It is possible to make an XMLHttpRequest synchronous, but that can lead to other problems. It can hang the browser as it blocks all other actions from happening. So if you want to show a loading animation, it most likely will not execute.
You can make your AJAX request synchronous. https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Synchronous_and_Asynchronous_Requests
var request = new XMLHttpRequest();
// Last parameter makes it not asnychronous
request.open('GET', 'http://www.mozilla.org/', false);
request.send(null);
// Won't get here until the network call finishes
if (request.status === 200) {
console.log(request.responseText);
}
However, that will block the UI while waiting for the server to respond, which is almost never what you want. In that case, you should use a callback to process results.
Here's an example using a callback without relying on a global variable. You should always run away from those
function ShowInserisciCommerciale( ) {
getElementiEsistenti(function(responseText) {
JSON.parse(responseText);
});
}
function getElementiEsistenti(successCallback){
var url = "http://127.0.0.1:8080/Tesi/Ingredienti";
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", url, false);
xmlHttp.send(null);
xmlHttp.setRequestHeader("Content-type",
"application/x-www-form-urlencoded");
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) // COMPLETED
{
if (xmlHttp.status == 200) // SUCCESSFUL
{
successCallback(xmlHttp.responseText);
} else {
alert("An error occurred while communicating with login server.");
}
}
};
}
Please help, I have been looking at this all day and I know there must be a simple fix!
How do I pass results back to textService so that I can make a call such as
textResult = textService(text to pass in);
I don't want to use a global variable if I can avoid it.
This is the code
function textService(text){
req.open("GET", "http://....?text="+text, true);
req.onload = showResults;
req.send(null);
}
function showResults() {
results = req.responseXML.getElementsByTagName("Result");
}
Thank you in advance
function textService(text){
// set flag to false for sync requests
req.open("GET", "http://...?text="+text, false);
req.send(null);
// browser will be stalled till request is complete.
if(req.status == 200 && req.readyState == 4) {
return req.responseXML.getElementsByTagName("Result");
} else {
return 'request failed';
}
}
// javascript will stall till request is complete.
var results = textService('someText');
Note, making synchronous request can be harmful, if a request fails, it might stall the browser indefinatly. It's better to do it asynchronously.
function textService(text, callback){
// async is true by default, no need to pass 3rd param.
req.open("GET", "http://...?text="+text);
req.send(null);
req.onreadystatechange = function(){
if(this.readyState == 4 || this.status == 200) {
callback(this.responseXML);
}
}
}
textService('someText', function(xml){
// do stuff with XML.
});
Just need switch your coding mind to async programming ;)
You can use this
function showResults() {
results = this.responseXML.getElementsByTagName("Result");
}