Performing a synchronous Ajax request from jQuery? - javascript

I know it sounds like something that's been asked before, but for all my hunting, I can't find anything matching what I'm looking for.
I'm working on a project that's rather heavily based on Ajax. I'm using jQuery, but even with its beautifully streamlined code, it's still messy when I've got it to the point that the code is exactly the same, except for one single command passed through the data field.
So I tried setting it up inside a handler function, like so:
function _call(task, opts, async) {
if(typeof async !== "boolean") { async = true; }
opts = $.extend({}, opts, options);
$.ajax({
url: "myphpfile.php",
dataType:"JSON",
type:"POST",
async:async,
data: { task: task, opts: opts }
}).done(function(data) { return data; });
}
For those who read through, you'll notice that there's a var,
options, that hasn't been defined in the example. It has actually
been assigned, it's just been omitted for clarity purposes.
I came to realize that this doesn't work, as even when it's set to async: false, the code still continues after the call of _call(...), therefore not getting the results in time. I've tried a few different variations, including passing an anonymous function to the handler and then using that as the .done() function, but it wouldn't interact with outside variables, defeating the purpose.
All I'm looking for is a system that will let me use it something like this:
var returnedData = _call("thisismytask");
var returnedDataWithOptions = _call("thisisanothertask", {'option': 'option1'});
I really hope this is possible. I'm sure it would be, as the main purpose of functions is to remove the need for unnecessarily repeated code.
Thanks. :)

You could do this:
function _call(task, opts) {
opts = $.extend({}, opts, options);
return $.ajax({
url: "myphpfile.php",
dataType:"JSON",
type:"POST",
data: { task: task, opts: opts }
});
}
It removes the need for passing a callback into _call, but functions just the same.
_call("thisisanothertask", {'option': 'option1'}).then(function(data) {
// function body here
});

you are probably best doing this
function _call(task, opts, callback) {
opts = $.extend({}, opts, options);
$.ajax({
url: "myphpfile.php",
dataType:"JSON",
type:"POST",
data: { task: task, opts: opts }
}).done(function(data) { callback(data); });
}
use like this
_call("thisisanothertask", {'option': 'option1'}, function(data) {
//do things with data
});
You cant really do this, as _call cant return straight away as it may take a while to get a response and even if you could it could lock your browser which is not good.
var returnedData = _call("thisismytask");
var returnedDataWithOptions = _call("thisisanothertask", {'option': 'option1'});
you need to use it like this:
_call("thisismytask", null, function(returnedData) {
//use returnData
});
_call("thisisanothertask", {'option': 'option1'}, function(returnedDataWithOptions) {
//use returnedDataWithOptions
});
If you needed the result of thisismytask before thisisanothertask you would have to do:
_call("thisismytask", null, function(returnedData) {
_call("thisisanothertask", {'option': 'option1'}, function(returnedDataWithOptions) {
//use returnData
//use returnedDataWithOptions
});
});

You should be using callbacks. You also shouldn't be using async: false as this will block the UI thread in browser. You can use jQuery.when() to sync your various tasks. First change your method like this:
function _call(task, opts) {
opts = $.extend({}, opts, options);
return $.ajax({
url: "myphpfile.php",
dataType:"JSON",
type:"POST",
data: { task: task, opts: opts }
});
}
Now you can call it like this:
$.when(
_call("thisismytask"),
_call("thisisanothertask", {'option': 'option1'})
).done(function(firstCallResults, secondCallResults) {
//*CallResults is an array with the following structure: [data, statusText, jqXHR]
var returnedData = firstCallResults[0];
var returnedDataWithOptions = secondCallResults[0];
...
});
This way you keep all the benefits of AJAX asynchrounous nature (those tasks will run in parallel unless server doesn't support it) and get your results back together when they are all available.

I found a solution. #Slavo pointed it out to me.
https://stackoverflow.com/a/6685294/563460
As you're making a synchronous request, that should be
function getRemote() {
return $.ajax({
type: "GET",
url: remote_url,
async: false,
}).responseText; }
Example - http://api.jquery.com/jQuery.ajax/#example-3
Now I just have to decode from text to proper JSON. Thank you everyone. :)

Use jQuery's syntax -
its worked for me,
$.ajaxSetup({async: false});

Related

jQuery AJAX issue? Or JS OOP scope issue?

I am trying to create a database handler class in javascript. I would like to call the class by simply using:
var databaseHandler = new DatabaseHandler();
result = databaseHandler.getResult("SELECT * FROM login");
I have created the class and used a callback for the ajax function (so as to wait for the ajax result to be returned). But all I am still receiving "undefined" as my result. If I use console.log(a) inside of the onComplete function, I get an array of the intended results.
(function(window){
//Database class
function DatabaseHandler(){
//Query
this.query = function(query, whenDone){
request = $.ajax({
url: "../optiMizeDashboards/php/DatabaseQuery.php",
type: "POST",
data: {query : query},
dataType: "JSON"
});
request.done(function(output) {
whenDone(output);
});
request.fail(function(jqXHR, textStatus) {
console.log(textStatus);
});
};
//Get result
this.getResult = function(query){
this.query(query, this.onComplete);
};
//Ajax callback
this.onComplete = function(a){
return a;
};
}
//Make available to global scope
window.DatabaseHandler = DatabaseHandler;
}(window))
My question is: Is this something to do with the variable scope, or the way that ajax works? I have read all the answers explaining that ajax is ASYNC and I thought I had handled that by using a callback function "onComplete"
Any help on this topic would be greatly appreciated!
You will not be able to return result immediately from calling getResult because underlying jQuery POST request is Asynchronous, instead you need to be passing a callback function which eventually will receive a result from server.
something like that:
(function(window){
//Database class
function DatabaseHandler(){
//Query
this.query = function(query, whenDone){
request = $.ajax({
url: "../optiMizeDashboards/php/DatabaseQuery.php",
type: "POST",
data: {query : query},
dataType: "JSON"
});
request.done(function(output) {
whenDone(output);
});
request.fail(function(jqXHR, textStatus) {
console.log(textStatus);
});
};
//Get result
this.getResult = function(query, callback){
this.query(query, callback);
};
}
//Make available to global scope
window.DatabaseHandler = DatabaseHandler;
}(window))
// then use it like so
var databaseHandler = new DatabaseHandler();
result = databaseHandler.getResult("SELECT * FROM login", function(data) {
//do something with data
});
PS: exposing direct SQL access to the databse on the client is very dangerous though, and I would not recommend doing that

Uncaught TypeError: object is not a function (in AJAX callback)

I am trying to update a FullCalendar object using a function that receives an array of events.
$('#sh1_cal').fullCalendar({
events: function(callback) {
$.ajax({
type: 'GET',
url: 'http://localhost:8080/getEvents',
dataType: 'json',
success: function(reply) {
//var events = [];
console.log("printing " + reply.first)
alert(typeof reply.first);
callback(reply.first);
}
});
}
});
Reply is intended to be an object containing two arrays as its properties. I'm extracting the first, and it seems that the typeof alert is returning the correct type, but the callback is not working. Any suggestions?
I have not used this plugin but from the docs (http://arshaw.com/fullcalendar/docs/event_data/events_function/) it looks like the events function takes 3 parameters: start, end, and callback.
Start and end are date objects indicating when the event starts and ends. The way you have it now, that function thinks there is a date object called 'callback' which is why you're getting the error. In JavaScript the name of the parameter is not important (for example you can call it 'cb' or 'foo' instead of 'callback') but the order is.
Try (untested):
$('#sh1_cal').fullCalendar({
events: function(start, end, callback) {
$.ajax({
type: 'GET',
url: 'http://localhost:8080/getEvents',
dataType: 'json',
success: function(reply) {
callback(reply.first);
}
});
}
});
Try this:
$('#sh1_cal').fullCalendar({
events: 'http://localhost:8080/getEvents'
});
Shouldn't be any need for writing your own ajax call, it's built in.
If that doesn't work, can you post the output of your JSON feed?
try this and let me know if it works:
$('#sh1_cal').fullCalendar({
events: function(cb) {
$.ajax({
type: 'GET',
url: 'http://localhost:8080/getEvents',
dataType: 'json',
success: function(reply) {
return cb(reply.first);
//or try: cb(reply.first);
}
});
}(callback)
});
if not that, remove the return on the callback.
did either work?
*please note: I assume that "callback" is a function you are passing in and have instantiated it somewhere.
Event (As Function) in fullcalendar has been changed. Now the third parameter is timezone.
Further information on FullCalendar Documentation v2

get a callback function to add to object javascript

I have an issue with a method ive created for an object ive created. one of the methods requires a callback to another method. the problem is i cant add the data to the object that called the method. it keeps coming back as undefined. otherwise when i send the data to the console it is correct. how can i get the data back to the method?
var blogObject = new Object();
var following = [...];
//get posts from those blogs
blogObject.getPosts = function () {
var followersBlogArray = new Array();
for (var i = 0; i < this.following.length;i++){
var followersBlog = new Object();
// get construct blog url
var complete_blog_url = ...;
i call the getAvatar function here sending the current user on the following array with it.
followersBlog.avatar = blogObject.getAvatar(this.following[i]);
that part goes smoothly
followersBlogArray.push(followersBlog);
}
this.followersBlogArray = followersBlogArray;
}
here is the function that gets called with the current user in following array
this function calls an ajax function
blogObject.getAvatar = function (data) {
console.log("get avatar");
var url = "..."
this ajax function does its work and has a callback function of showAvatar
$(function() {
$.ajax({
type: "GET",
dataType: "jsonp",
cache: false,
url: url,
data: {
jsonp:"blogObject.showAvatar"
}
});
});
}
this function gets called no problem when getAvatar is called. i cant however get it to add the data to the followersBlog object.
blogObject.showAvatar = function (avatar) {
return avatar
}
everything in here works fine but i cant get the showAvatar function to add to my followersBlog object. ive tried
blogObject.showAvatar = function (avatar) {
this.followersBlog.avatar = avatar;
return avatar
}
that didnt work of course. it shows up as undefined. can anyone help?
so somethings like...
$(function() {
$.ajax({
type: "GET",
dataType: "jsonp",
cache: false,
url: url,
complete: function () {
this.avatar = data;
}
data: {
jsonp:"blogObject.showAvatar"
}
});
});
}
Welcome to the world of asynchronous programming.
You need to account for the fact that $.ajax() will not return a value immediately, and Javascript engines will not wait for it to complete before moving on to the next line of code.
To fix this, you'll need to refactor your code and provide a callback for your AJAX call, which will call the code that you want to execute upon receiving a response from $.ajax(). This callback should be passed in as the complete argument for $.ajax().
The correct option for setting the JSONP callback is jsonpCallback. The recommendation from the API for .ajax(...) is to set it as a function.
{
// ...
jsonpCallback: function (returnedData) {
blogObject.showAvatar(returnedData);
},
// ...
}

Problems with jQuery ajax function

I'm having a trouble since jQuery.ajax, in this particular case, doesn't seem to happen, so that the function always return NaN undefined as result:
function requestUploadedSearch()
{
var cookie = JSON.parse(readCookie("user_search_cookie"));
$.ajax({
dataType: "script",
async: false,
data: {
context: "search-get",
code: removeNull(cookie, cookie !== null, "code")
},
success: function(data)
{
return search_return["keywords"];
}
});
delete cookie;
}
I've also tried to write something like
success: function() { return "<nothing happens>"; }
But what I receive is undefined.
Please answer, I'm really freaking out with that.
Thanks in advance.
What you're trying to do is fundamentally impossible. Your ajax operation is asynchronous (no it isn't durrr).
Instead, re-architect your API:
function requestUploadedSearch( callback )
{
var cookie = JSON.parse(readCookie("user_search_cookie"));
$.ajax({
dataType: "script",
async: false,
data: {
context: "search-get",
code: removeNull(cookie, cookie !== null, "code")
},
success: function(data)
{
callback( search_return["keywords"] );
}
});
delete cookie;
}
Then, when you invoke it, instead of expecting a return value, pass in a function to respond to the returned data:
requestUploadedSearch( function( value ) {
// ... do stuff with "value" ...
});
edit — Doh! #nickd is correct; since you're making the call synchronously (which you really should seriously consider not doing; it's pretty bad for your user experience) the story is different. Still, however, the approach above would work.
Pointy is pointing (hah) you in the more usual way of doing things. However as you have async: false set, your success: function is never called. Putting
return search_return["keywords"];
after the delete cookie line will return as you have it in your example, but you aren't using the result of the ajax call anywhere I can see, so I'm not sure that there's any point.

jQuery ajax function return

I have this function that embeds flash :
function embedswfile(target, swf, base, width, height) {//dosomething}
And I want to call the function like this
embedSwf("flashgame",decode("<?=base64_encode($path['location'])?>"),decode("<?=base64_encode($path['base_directory'])?>"),"800","600" )
The idea is that whenever someone looks for any swf inside my website,he wont find anything clean.I will change the encoding algorithm,but this is just temporary. In order for that function to work,whenever I call the function 'decode' it must return a single value. PHP contains
<?php
echo base64_decode($_POST['s']);
?>
I tried this but it still wont work
var globvar;
function processdata(newmsg) {
globvar = newmsg;
}
function decode(s){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(newmsg){
processdata(newmsg);
}
});
return globvar;
}
Important:
Forget about using Ajax and encoding, decoding the path. What do you think you gain from it? Security? No. One can figure out that this is bas64 encoded or he just monitors the network traffic and reads the response from the Ajax call.
Just do
embedSwf("flashgame","<? =$path['location']?>"),"<?=$path['base_directory']?>","800","600" )
Really, you cannot prevent someone else seeing the data and are just making things more complicated for you.
(Or you have to decrypt the data with JavaScript.)
(original answer is still correct nevertheless)
Ajax is asynchronous so something like var test = decode(s); will never work. The decode function will return before the Ajax call finishes.
Instead, put your logic into the callback handler. For example, if your code was this before:
var retdata = decode('s');
// here comes code that handles retdata
put the code into a function and call it from the success handler:
function process(retdata) {
// here comes code that handles retdata
}
function decode(s){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(newmsg){
process(newmsg);
}
});
}
This seems to be a very common problem to all beginners. You will find a lot of questions here that deal with the same problem.
Update:
It is not nice, but you could change the function to
function decode(s, cb){
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
success:function(data){
cb(data);
}
});
}
and do
decode("<?=base64_encode($path['location'])?>", function(location) {
decode("<?=base64_encode($path['base_directory'])?>", function(dir) {
embedSwf("flashgame",location,dir,"800","600" );
});
});
Update 2:
For completeness, you can make the Ajax call synchronous, by using async: false. Then this will work:
function decode(s){
var ret;
$.ajax({type: "POST",
url: "includes/decode.inc.php",
data: "s=" + s,
async: false,
success:function(newmsg){
ret = newmsg;
}
});
return sync;
}
var val = decode(s);
However, this will block the browser until the Ajax call finished. You have to test whether this matters in your case or not.
Update 3:
You could also change your PHP script to not only accept one parameter but several and process both strings in one go.

Categories