Javascript global variable not being set from ajax call [duplicate] - javascript

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Return Value from inside of $.ajax() function
I'm working on a CakePHP app that makes use of widespread AJAX calls to controllers. I'm stuck with one particular AJAX call in which I'm trying to assign the response from the controller to a JS global variable. Here is the code:
window.errors = "";
function setErrors(err) {
window.errors = err;
}
function ajaxCall(u, t, d, dt) {
var type = typeof t !== 'undefined' ? t : "post";
var dataType = typeof dt !== 'undefined' ? dt : "json";
var success = false;
var err = "";
$.ajax({url: url, data: "data=" + d, type: type, dataType: dataType,
success: function(d){
if(d.hasOwnProperty('success') === false) { //json response
for(var i in d) { //fetch validation errors from object
for(var j in i) {
if(typeof d[i][j] === "undefined") {
continue;
}
err += d[i][j] + "<br/>";
}
}
console.log(err); //<=== displays correct value
setErrors(err); //<=== but somehow this seems to be failing??
}
else {
if(d.success === "1") {
success = true;
}
}
}
});
return success; //<=== I suspect this might be the culprit
}
And this is how ajaxCall() is used:
function register() {
var data = {};
var $inputs = $("#regForm :input");
$inputs.each(function(){
data[this.name] = $(this).val();
});
data = {"User" : data }; //CakePHP compatible object
data = JSON.stringify(data);
//Here's the AJAX call
if(ajaxCall('https://localhost/users/add', 'post', data, 'json')) {
alert("Registered!");
}
else {
alert(window.errors); // <=== empty string
console.log("window.errors is: " + window.errors); // <=== empty string
}
}
But on the Chrome JS console, window.errors returns the correct value (non-empty, validation error string).
I found a similar question that possibly might be addressing my issue (the return success immediately following the $.ajax() is being executed before the success: callback). How can I fix this without drastically changing the code (also, I don't want to make this a synchronous call)?

Yes, you are right that the return statement runs before the success callback. You can't return the result from the function, as the function has to return before the success event can be handled.
Add a callback to the ajaxCall function, and call that instead of setting the success variable:
function ajaxCall(u, t, d, dt, callback) {
var type = typeof t !== 'undefined' ? t : "post";
var dataType = typeof dt !== 'undefined' ? dt : "json";
$.ajax({url: url, data: "data=" + d, type: type, dataType: dataType,
success: function(d){
if(d.hasOwnProperty('success') === false) { //json response
for(var i in d) { //fetch validation errors from object
for(var j in i) {
if(typeof d[i][j] === "undefined") {
continue;
}
err += d[i][j] + "<br/>";
}
}
callback(false, err);
} else {
callback(d.success === "1", "");
}
}
});
}
Send the code for handling the result into the ajaxCall function:
ajaxCall('https://localhost/users/add', 'post', data, 'json', function(success, err){
if (success) {
alert("Registered!");
} else {
alert(err);
}
});

Related

YQL AJAX cross domain request stopped working

I have been using the following code to successfully read the contents of an external webpage as a string - I haven't used this program in a month or so but it has suddenly stopped working even though the code has not been changed. I suspect the YQL API has been updated but I couldn't find any documentation that I could understand on this. (I am a beginner at JS). If someone could point me to how to update my code it would be much appreciated!
Code:
function formSubmitted(raceID) {
if(raceID.length < 4 && raceID > 0){
savedRaceID = raceID;
raceUrl = "http://www.bbk-online.net/gpt/lap"+raceID+".htm";
jQuery.ajax = (function(_ajax){
var protocol = location.protocol,
hostname = location.hostname,
exRegex = RegExp(protocol + '//' + hostname),
YQL = 'http' + (/^https/.test(protocol)?'s':'') + '://query.yahooapis.com/v1/public/yql?callback=?',
query = 'select * from html where url="{URL}" and xpath="*"';
function isExternal(url) {
return !exRegex.test(url) && /:\/\//.test(url);
}
return function(o) {
var url = o.url;
if ( /get/i.test(o.type) && !/json/i.test(o.dataType) && isExternal(url) ) {
// Manipulate options so that JSONP-x request is made to YQL
o.url = YQL;
o.dataType = 'json';
o.data = {
q: query.replace(
'{URL}',
url + (o.data ?
(/\?/.test(url) ? '&' : '?') + jQuery.param(o.data)
: '')
),
format: 'xml'
};
// Since it's a JSONP request
// complete === success
if (!o.success && o.complete) {
o.success = o.complete;
delete o.complete;
}
o.success = (function(_success){
return function(data) {
if (_success) {
// Fake XHR callback.
_success.call(this, {
responseText: data.results[0].replace(/<script[^>]+?\/>|<script(.|\s)*?\/script>/gi, '')
//THE ERROR IS COMING FROM ABOVE - REPLACE IS BEING CALLED ON A NULL OBJECT??
//SUGGESTS NO DATA RETURNED?
}, 'success');
}
};
})(o.success);
}
return _ajax.apply(this, arguments);
};
})(jQuery.ajax);
$.ajax({
url: raceUrl,
type: 'GET',
success: function(res) {
processData(res.responseText);
}
});
}
else{
alert("Please enter a valid race number...");
}
}
I have highlighted where the error is coming from - it appears that the function is not returning any data?

Passing For Loop Variable into AJAX Success

I have an issue with passing my for loop index variable into ajax success function.. I know this is a duplicate, but I've tried several other solutions that I've found and none seem to work for me..
Anyway, I have this code right here :
embeds = document.getElementsByClassName('kcode');
for (i = 0, l = embeds.length; i < l; i++) {
if (typeof embeds[i] != 'undefined' && typeof embeds[i].classList != 'undefined' && !embeds[i].classList.contains('filled')) {
embeds[i].classList.add('filled');
var embed = window.intext[embeds[i].getAttribute('data-k-kid')];
if (embed) {
embeds[i].classList.add('embed');
switch (embed.type.toLowerCase()) {
case 'sport_plugin':
if(sportData.selectedType.name == "Ranking Table") {
(function(i) {
jQuery.ajax({
url: url,
dataType: 'json',
success: function(response) {
var content = '';
if (table.name == "Western Conference" || table.name == "Eastern Conference") {
content+= '</div>';
embeds[i].innerHTML = content;
}
}
});
})(i);
}
break;
default:
embeds[i].style.display = "none";
}
embeds[i].classList.remove('kcode');
i--;
}
}
}
Now, what I'm trying to achieve -
I want to pass the embeds variable and the i variable of for loops index into my ajax response, so I could set the innerhtml of embeds[i] after the response is finished. I tried wrapping the ajax function in (function (i) {})(i); closure but it didint help. Any ideas? Thank You!
I think i variable should be global in that scope, so I would try to use it like this:
case 'sport_plugin':
if(sportData.selectedType.name == "Ranking Table") {
jQuery.ajax({
url: url,
dataType: 'json',
success: function(response) {
var content = '';
if (table.name == "Western Conference" || table.name == "Eastern Conference") {
content+= '</div>';
embeds[i].innerHTML = content;
}
}
});
}
break;
You can try to create a callback success function for the ajax. Before the ajax call. Something like this
var successCallback = function() {
var content = '';
if (table.name == "Western Conference" || table.name == "Eastern Conference") {
content+= '</div>';
this.embeds[this.i].innerHTML = content;
}
};
successCallback.i = i;
successCallback.embeds = embeds;
Note the "this." in front of the i.
And then your ajax:
jQuery.ajax({
url: url,
dataType: 'json',
success: successCallback
});
I have not tried it but it might work
I solved this problem myself, nontheless thanks for all the help and replies!
I simply used this function for getting my data, instead of usual ajax response..
_get = {
'sync': function (url) {
var xhr = typeof XDomainRequest != 'undefined' ? new XDomainRequest() : new XMLHttpRequest();
xhr.open('get', url, false);
xhr.send(null);
console.log('sync url ' + url);
//console.log(xhr.responseText); return {};
var data = {};
if (xhr.status == 200) {
data = JSON.parse(xhr.responseText);
}
return data;
}
};
And then just
var response = _lr.get.sync(url);

Use Parse Query in then() when using Cloud Code

I can’t seem to get this simple Parse query to work in my cloud code then() it works outside of this but when i place the code inside of this then function nothing happens. The variables are just placeholders for now in terms of testing but i have the default TestObject class you get when you start Parse from the beginning but for some reason it just keeps on returning nothing.
Here is the full function that i am currently using.
// Function which will get the data from all the links passed into the function
Parse.Cloud.define("myNews", function (request, response) {
var promises = _.map(import_io_keys, function (news_api_key) {
return Parse.Cloud.httpRequest({
method: 'GET',
url: "https://api.import.io/store/connector/" + news_api_key + "/_query?input=webpage/url:https%3A%2F%2Fwww.designernews.co%2Fnew&&_apikey=xxxxxxxxxxxxxxxxxx",
headers: {
'Content-Type': 'application/json;charset=utf-8'
}
}).then(function (httpResponse) {
result = JSON.parse(httpResponse.text);
var success = false;
var news_icon = "";
var news_source_name = "";
var query = new Parse.Query("TestObject");
query.find({
success: function(results) {
success = true;
news_icon = results[0].get("foo");
news_source_name = results[0].get("foo");
response.success("done" + news_icon);
},
error: function() {
success = false;
response.error("Query lookup failed");
}
});
for (var story in result.results) {
if(story.length > 0){
if (story["article_link/_text"] !== "" && story["article_link"] !== "" && story["article_time"] !== "") {
if(success){
// Do the stuff later
}
}
}
}
});
});
Parse.Promise.when(promises).then(function () {
console.log("Got all the stories");
response.success(newsJsonData);
}, function () {
response.error("No stories");
console.log("API KEY IS: " + request.params.keys);
});
});

Function as parameter in Jquery Ajax

Is it possible to put a function into a parameter for Jquery Ajax like below. dataType and data are given as functions. dataType returns a value of JSON if the returntype is JSON and text if isJson is false.
dataVal and dataVar are arrays containing the parameter names and values used to construct the data paramater. The result of the data: function would be a string as:
{dataVar[0]:dataVal[0],dataVar[1]:dataVal[1],.....,}
I'm getting an error when I try this, so, just wanted to know if this method was possible.
function getAjaxResponse(page, isJson, dataVar, dataVal, dfd) {
$.ajax(page, {
type: 'POST',
dataType: function () {
if (isJson == true) {
return "JSON";
} else {
return "text";
}
},
data: function () {
var dataString = '{';
for (var i = 0; i < dataVar.length; i++) {
dataString = dataString + dataVar[i] + ':' + dataVal[i] + ',';
}
console.log(dataString);
return dataString + '}';
},
success: function (res) {
dfd.resolve(res);
}
});
}
Edit
As per answers and comments, made the changes. The updated function is as below. This works:
function getAjaxResponse(page, isJson, dataVar, dataVal, dfd) {
$.ajax(page, {
type: 'POST',
dataType: isJson ? "JSON" : "text",
data: function () {
var dataString ="";
for (var i = 0; i < dataVar.length; i++) {
if (i == dataVar.length - 1) {
dataString = dataString + dataVar[i] + '=' + dataVal[i];
} else {
dataString = dataString + dataVar[i] + '=' + dataVal[i] + ',';
}
}
return dataString;
}(),
success: function (res) {
dfd.resolve(res);
}
});
}
And my original question is answered. But apparently, data is not getting accepted.
The return value of the data function is just treated as the parameter name and jquery just adds a : to the end of the request like so:
{dataVar[0]:dataVal[0]}:
So, my server is unable to pick up on the proper paramater name.
From the manual:
data
Type: PlainObject or String
So no.
Call the function. Use the return value.
data: function () { ... }();
// ^^ call the function
Not that way. But it will work with a little change:
(function () {
if (isJson == true) {
return "JSON";
} else {
return "text";
}
})()
That should work. You just call the function immidiately after you created it. This way, dataType is a String and the script will work.
Same with data. Also use the (function(){})()-notation here
jquery just adds a : to the end of the request like so:
{dataVar[0]:dataVal[0]}:
No, your devtools display does. However, as you're data string does not contain a = sign, and you send the content as application/x-www-form-urlencoded, the whole body is interpreted as if it was a parameter name.
For sending JSON, you should:
use contentType: "application/json"
use data: JSON.stringify(_.object(dataVar, dataVal))1
to ensure valid JSON is sent with the correct header (and correctly recognised as such at the server).
1: _.object is the object function from Underscore.js which does exactly what you want, but you can use an IEFE as well:
JSON.stringify(function(p,v){var d={};for(var i=0;i<p.length;i++)d[p[i]]=v[i];return d;}(dataVar, dataVal))
You need to call the function with parenthesis like below:
function func1(){
//func1 code in here
}
function func2(func1){
//func2 code in here
//call func1 like this:
func1();
}
So, you can use like this:
data: function () {
//your stuff her
}(); // which mean you are having data()

Retrieve data from ajax query

So I've got a website where I want to click a button, check to see if the user has certain permissions, and if so popup a window to a new web page. On the java script I've got something like this:
function sendAjax(methodName, dataArray, success, error, category) {
var error2 = error || function () { };
$.ajax({
type: 'POST',
url: '/PermissionChecker' + methodName,
data: JSON.stringify(dataArray),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (r, s, x) { if (!success || success(r, s, x) != false) if (typeof (window.ChangeLogAdd) == 'function') { ChangeLogAdd(category); } },
error: error2
});
}
function CheckPermissions() {
sendAjax("CheckPermission", null, function (data) { var permission = eval('(' + data + ')'); if (permission == true) { alert('yay'); } else { alert('nay'); } }, null, 'Check Permission');
}
And the C# side is a simple function that does an if check and returns a bool. The function call goes through fine, but when it returns the bool I get a javascript error "Expected ']'". I assume this has something to do with my success function:
function (data) {
var permission = eval('(' + data + ')');
if (permission == true) {
alert('yay');
}
else {
alert('nay');
}
}
seeing as I didn't get this error before I tried what I'm doing there, so I was wondering how I would go about getting the data back from the ajax call to make pass the permission == true if/else check
Don't use eval for this purpose. It's unsafe and the source of many bugs. Just make the server respond with JSON and use $.getJSON.

Categories

Resources