Returning jQuery Ajax Post - javascript

I wish to use the jQuery.post class to return (not alert) the response within a function.
The following gives an alert with the appropriate value:
function test_func() {
$.post("test.php", { cmd: "testing" }, function (data) { alert(data); })
}
(displays alert with appropriate value)
I tried the following:
function test_func() {
return $.post("test.php", { cmd: "testing" }, function (data) { return data; })
}
(returned object)
function test_func() {
var tmp;
$.post("test.php", { cmd: "testing" }, function (data) { tmp=data; })
return tmp;
}
(returned undefined)
var tmp;
function setTmp(n) {
tmp=n;
}
function test_func() {
t=$.post("test.php", { cmd: "testing" }, function (data) { setTmp(data); })
}
(returned undefined)
function test_func() {
t=$.post("test.php", { cmd: "testing" })
return t.responseText;
}
(returned undefined)
So what's the deal? How can I make "test_func()" return the data response text?

Being an asynchronous request, you aren't able to get a response as soon as you call the function. Instead, the function that you pass to $.post is intended to be a callback that will perform some action as soon as the response is complete. Consider the following:
function myCallback(response) {
// do something with `response`...
}
function test_func() {
$.post("test.php", { cmd: "testing" }, myCallback)
}
Instead of directly returning a response, you can instead manipulate it as needed in the myCallback function.

The deal is ajax is asynchronous one possible solution is to set it as sync like
$.ajaxSetup({
async:false
});
and then
function test_func() {
var temp;
t=$.post("test.php", { cmd: "testing" })
return t.responseText;
}
the answer is only to make your current setup work else there are better ways to deal with it

Related

Effectively using $.when.apply(...) on custom promises

I'm using $.when.apply(methodArray[...]) in order to return the method callback arguments in my overall "done" callback. This works fine when the methods are $.ajax(options) calls, but sometimes the member methods are synchronous. I've tried every combination of $.Deferred, new Promise, $.when().then(...) that I can come up with, but I simply can't get the data from my sync call to show up as arguments in my done() callback. Here's an abbreviated example:
var loader() {
var obj = this;
this.execute = function (force, success, fail) {
if (!force) {
var data = {message: "This is cached data"};
if (data) {
//this does not return data to when.apply
return $.when().done(function () {
if (success) success(data);
return data;
});
}
}
return execute(success, fail); //this works fine
}
function execute(success, fail) {
return $.ajax({
type: obj.method,
url: obj.url,
data: obj.data,
dataType: obj.dataType || "json",
success: function (data) {
if (obj.cacheName) setCacheData(obj.cacheName, data);
if (obj.success) obj.success(data);
if (success) success(data);
},
fail: function (err) {
if (obj.fail) obj.fail(err);
if (fail) fail(err);
}
});
}
}
var selected = [] //array of loader objects with "execute(...)" command
$.when.apply($, $.map(selected, function (l) {
return l.execute(force, l.success, l.fail);
})).done(function () {
if (success) success($.map(arguments, function (a) {
return a[0]; //a is undefined on sync method
}));
}).fail(function () {
if (fail) fail($.map(arguments, function (a) {
return a[0];
}));
});
Basically, after the first (ajax) call, the data is cached. On subsequent calls, the "execute" function will just get the data from cache instead of the ajax call.
As mentioned - the when.apply code above works perfectly when the "execute" command is returning an $.ajax call. But when it is returning data that is cached (ie: from a previous ajax call) I cannot get the data passed back in the callback arguments.
How do I write this "execute" function to return EITHER the cached data or the $.ajax call as a promise - so that it is transparent (no difference) to the "when.apply"??
Another way I tried it:
if (data) {
var df = $.Deferred();
if (success) success(data);
df.resolve(data);
return df.promise(data);
}
That also did not work...

Using promises in javascript - only hitting the server once

I am trying to fully understand the usage of promises and the benefits they give. I have an AJAX call that grabs a bunch of data from the server. Right now I do not have promises implemented and the code hits the server anytime the user changes a view (all using the same data, just the way it looks).
Here is the promise I am trying to add:
function feedData(arr){
//data being initialized
this.initData();
}
feedData.prototype = {
constructor: feedData,
getData:function(){
return $.ajax({
url: 'php/getData.php',
dataType: 'json',
data: {
//data being sent over
}
});
},
initData:function(){
this.getData()
.done(function(result){
console.log(result.length);
})
.fail(function(x){
console.log(x);
});
},
....
}
I may not being fully understanding asyc behavior here. What I would have liked to do is get the result from getData and populate an object full of data that would be called whenever the user changes the view. From all I've read, thats not what promises are used for. Instead I should be returning a promise and using that data again? (Maybe this is my error of thought)
So my question is, once the data from getData is returned from AJAX, is there a way to return the promise and use the .done multiple times without hitting the server ever time? Meaning, since I will be using that same data and I can't save it to a global object, how could I achieve this?
Keep track of the promise returned by $.ajax(). This makes the call only once (in the constructor) regardless of how often you call getData():
function FeedData() {
this.data_promise = $.ajax({
url: 'php/getData.php',
dataType: 'json',
data: {}
});
}
FeedData.prototype = {
constructor: FeedData,
getData: function () {
return this.data_promise;
}
}
var feed = new FeedData();
feed.getData().then(function () {
/* .. */
});
You can also delay fetching until you call getData() for the first time:
function FeedData() {
this.data_promise = null;
}
FeedData.prototype = {
constructor: FeedData,
getData: function () {
if (this.data_promise === null) {
this.data_promise = $.ajax({
url: 'php/getData.php',
dataType: 'json',
data: {}
});
}
return this.data_promise;
}
}
Note, jQuery.ajax() returns a jQuery promise object.
At first successful $.ajax() call define a property to store the data at the instance. When .then() is called assign the result of $.ajax() to the value of the property at the object as a resolved Promise.
Retrieve the value from the object using instance.property.then().
function feedData(arr) {
var feed = this;
this.getData = function() {
return $.ajax({
url: 'php/getData.php',
dataType: 'json',
data: {
//data being sent over
},
// set `context` : `this` of `$.ajax()` to current `fedData` instance
context: feed
});
};
this.initData = function() {
// note `return`
return this.getData()
.then(function(result) {
console.log(result.length);
// define `this.promise` as a `Promise` having value `result`
this.promise = Promise.resolve(result);
return result;
})
.fail(function(x) {
console.log(x);
});
}
}
var request = new feedData();
request.initData().then(function(data) {
console.log(data)
});
// this will not make antoher request
request.promise.then(function(res) {
console.log("result:", res)
});
function feedData(arr) {
var feed = this;
this.getData = function() {
// do asynchronous stuff; e.g., `$.ajax()`
return $.Deferred(function(dfd) {
dfd.resolveWith(feed, [
[1, 2, 3]
])
});
};
this.initData = function() {
// note `return`
return this.getData()
.then(function(result) {
console.log(result.length);
// define `this.promise` as a `Promise` having value `result`
this.promise = Promise.resolve(result);
return result;
})
.fail(function(x) {
console.log(x);
});
}
}
var request = new feedData();
request.initData().then(function(data) {
console.log(data)
});
// this will not make another request
request.promise.then(function(res) {
console.log("result:", res)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

javascript promise return recursively to index

Ok, so I've got a loop like so:
underscore.each(dom.paramArray, function(value, i) {
fetchDataFromServerWithParams(value, i);
});
In my current example it loops 3 times, idealy like: 0,1,2
However, when I log the index of the function called, it logs: 1,0,2, why ?
And how can I get it to call the function recursively, so first it will process the function with index:0, then index:1, and lastly, index:2
I think it has something to do with the functions I am calling (buildResult and buildSubResult), but Im really not sure?
The function that is called by the loop looks like:
function fetchDataFromServerWithParams(param, index) {
//Create promise
let getData = $.ajax({
headers: {
Accept : "text/plain; charset=utf-8",
"Content-Type": "text/plain; charset=utf-8"
},
type: "GET",
url: configuration.apiEndpoint,
data: { id: param},
dataType: "json"
});
//When done processing promise, build result
getData.then(function (data) {
let generatedData;
console.log(index);
if(index === 0) {
generatedData = buildResult(data);
} else {
$.each($("ul.material a"), function( index, value ) {
var target = $(this).parent();
if($(this).data("id") == param) { //Refactor later to ===
target.parent().addClass("open-folder");
target.parent().parent().find("ul").addClass("open-folder");
generatedData = buildSubResult(data, target);
}
});
}
}), function(xhr, status, error) {
// Handle errors for any of the actions
handleError(error);
};
}
you can use async library or any other library for this purpose
also you can change the line
getData.then(function (data) {
to
return getData.then(function (data) {
and use this code instead of your underscore loop
(function sequenceCall(index){
fetchDataFromServerWithParams(dom.paramArray[index], index).then(function(){
sequenceCall(index+1);
});
})(0);

JQuery AJAX - Filter before .done()

My application has a lot of AJAX calls, each of them return a JSON response. Instead of validating the data in each of the the .done() calls, I'm trying compact the code.
What we have so far
$.ajax({
url: 'test',
type: 'GET',
data: {
_token: token
},
dataFilter: function(jsonResponse) {
return isValidJson(jsonResponse);
}
}).done(function(jsonResponse) {
// do things
});
isValidJson(jsonResponse) {
try {
var parsedJson = $.parseJSON(jsonResponse);
if (parsedJson.error == 1) {
notificationController.handleNotification(parsedJson.message, 'error');
return false;
}
} catch (err) {
notificationController.handleNotification('A server-side error occured. Try refreshing if the problem persists.', 'error');
return false;
}
return jsonResponse; // Have to return the original data not true
}
The expected behavior is that if dataFilter returns false, it will trigger .fail(), if it returns true then it will continue to .done(). Instead, it just continues to .done() with the result of isValidJson().
Is there also a way to make .fail() do something standard like send a notification to the user without having to put it under every AJAX call?
Easiest way is to create a shorthand for $.ajax, by extending it.
Extending the AJAX call
jQuery.extend({
myAjax: function(params){
// Here we can modify the parameters and override them e.g. making 'error:' do something different
// If we want to add a default 'error:' callback
params.error = function() {
console.log('its failed');
};
// or you can specify data parse here
if (params.success && typeof params.success == 'function') {
var successCallback = params.success;
var ourCallback = function(responseJson) {
if (isValidJson(responseJson)) { // Validate the data
console.log('The json is valid');
successCallback(responseJson); // Continue to function
} else {
console.log('The json is not valid');
}
}
params.success = ourCallback;
}
return $.ajax(params);
}
});
Now everytime you want to make an AJAX call in your application, you DO NOT use $.ajax({}). Instead, you use $.myAjax({});
Example
$.myAjax({
url: 'domain.com',
type: 'GET',
success: function(data) {
// Do what you'd do normally, the data here is definitely JSON.
},
error: function(data) {}
});
And this special function will handle all errors same way, no need to write those validators every time.
Try to do it like this (Not tested):
var jxhr = $.ajax({
url: 'test',
type: 'GET',
data: {
_token: token
},
dataFilter: function(jsonResponse) {
if (!isValidJson(jsonResponse)) {
jxhr.abort();
}
return jsonResponse;
}
}).done(function(jsonResponse) {
// do things
});
By using this strategy - you are violating "separation of concern" strategy.
Ajax should resolve or reject according to its action. Not according if response is JSON or not.
A possible solution : ( sure there are also another solutions)
function GetSanitized(d) {
return d.then(function(a) {
if (a.indexOf('{') > -1) //check if json ( just for example)
return $.Deferred().resolve(JSON.parse(a)); //return object
else
return $.Deferred().reject(a); //reject
},
function() {
return $.Deferred().reject("ajax error"); //ajax failed
}
);
}
var ajax = $.Deferred();
GetSanitized(ajax) .then(function (a){alert(" Json p's value is "+a["p"]);},function (a){alert("Error"+a);});
ajax.resolve("{\"p\":2}"); //simulate ajax ok , valid json
//ajax.resolve("\"p\":2}"); //simulate ajax ok , invalid json
//ajax.reject("\"p\":2}"); //simulate ajax bad , valid json
http://jsbin.com/vozoqonuda/2/edit

Getting the result of jquery .post() function

I need to find out how to access "data" variable outside of the post function. It will return either valid or invalid so I can finish the main function logic.
Is this the right way to do it:
$('#form_choose_methods').submit(function(){
var voucher_code = $('#voucher_code').val();
var check = $.post(baseURL+"ajax.php", { tool: "vouchers", action: "check_voucher", voucher_code: voucher_code },
function(data) {
});
alert(check);
return false;
});
check seems to be the object, but I want to know how to access result of it.
You can access the response in the success callback you use
$.post(baseURL+"ajax.php", { tool: "vouchers", action: "check_voucher", voucher_code: voucher_code },
function(data) {
// you can access the response in here
alert(data);
});
Ajax calls are asynchronous, so you will only have access to the result from the callback whenever it completes..
$('#form_choose_methods').submit(function () {
var voucher_code = $('#voucher_code').val();
$.post(baseURL + "ajax.php", { tool: "vouchers", action: "check_voucher", voucher_code: voucher_code },
function (data) {
if (data == "valid") {
//do seomthing
}
else {
//do something else
}
});
});

Categories