how to get the values passed into an ajax post - ajax

Here is my codes,
function getMods(name){
var init;
$.ajax({
type: "POST",
url: "init.php",
data: { 'id': getID(), 'Name': name },
cache: false,
success: function(data)
{
return data;
},
async:false
});
}
function init(){
var gm = '<br/>';
var gm1 = getMods('Name');
$('#brand').append(gm1);
var gm2 = getMods('Owner');
var gm3 = getMods('Admin1');
var gm4 = getMods('Admin2');
var gm5 = getMods('Admin3');
var gm6 = getMods('Admin4');
$('#online3').append(gm2 + gm + gm3 + gm + gm4 + gm + gm5 + gm + gm6 + gm);
}
The getMods() returned "undefined". When i use this code:
alert(data);
The page alerted the correct values.
Here is the php file init.php:
<?php
include('dbconnect.php');
if(isset($_POST['id']) && isset($_POST['Name'])){
$id = $_POST['id'];
$name = $_POST['Name'];
$init = chatMods($name,$id,$username,$password);
echo $init;
}
?>
And I add the async in the getMods().

You should make the distinction between a return value of a function (getMods() in your case) and a callback function (success).
In your code, you call getMods() which in fact doesn't return any value, hence you get undefined.
The success callback happens only after a while, after your function had already returned.
One possible solution for you (though not the greatest because it locks your JS processing) is to use an Ajax call in a synchronous way. A call that only returns when an answer from the server has been received. Use async: false in your $.ajax call, capture your return value and then return it. See this example: https://stackoverflow.com/a/2592780/290343
You should be aware, of course, that your Ajax calls might fail and you need to take that into account. Also, your code might run really slow because it does 6 remote calls to a server.

Related

Ajax calls in for loop

I have the function shown below, it just makes a request to a bunch of endpoints housed in an array. Right now I have the Ajax calls be sync (as opposed to the native async).
This is because although when async it does cycle through the urls and makes the calls correctly, the name of the API, which I set to the variable 'name', will only display the last name in the list:
When it should display like this (which it does only if I set the Ajax call to sync):
I'm pretty sure this is due to the fact that the threads from the ajax calls can take any given time to complete while the for loop has finished its iterations way before, thus having only the las name in the list for display.
How can I keep the calls async while also having the names synched to the response of each call?
Thanks.
function isAlive(service) {
var buildIsAliveBox = function (isAlive, name, xhr) {
var isAliveOuterCnt = $('#isAliveOuterCont' + service);
var applyClass = isAlive ? 'alive' : 'dead';
var status = xhr.status == 0 ? 'Failed' : xhr.status;
var xhrMessage = handleHttpResponse(xhr);
var isAliveBox = $('<div class="' + applyClass + ' isAliveBox" class="btn btn-secondary" data-toggle="tooltip" data-placement="bottom" title="' + xhrMessage + '"><p class="svrName">' + name + '</br>' + status + '</p></div>');
isAliveOuterCnt.append(isAliveBox);
};
var svce = service.toLowerCase();
for (var i = 0; i < environments.qa[svce].healthUrls.length; i++) {
var data = environments[envSwitch][svce].healthUrls[i];
var name = data.split(',')[0];
var url = data.split(',')[1];
$.ajax({
url: url,
type: 'GET',
async: false,
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
},
success: function (data, status, xhr) {
buildIsAliveBox(true, name, xhr);
},
fail: function (xhr, textStatus, errorThrown) {
buildIsAliveBox(false, name, xhr);
},
error: function (xhr, status, err) {
buildIsAliveBox(false, name, xhr);
}
});
}
}
Change var to let, at least for name (but ideally for the other variables as well to avoid stumbling upon this issue again later on).
var is function-scoped and not block-scoped and hence the same data, name and url variables are reused every iteration. And the response from the AJAX call comes back long after your loop finished running, so by that time those variables will have the values they last got assigned (in the last iteration of the loop).
With let you get a new scope for every iteration so each AJAX call will get a different name variable etc. it accesses in the callback.

How to use Angular service in place of Ajax url property

Here is code:
loader:function(param,success,error){
$.ajax({
//url: 'http://localhost/mvcController?assetid=1&dataformat=attribute',
url: assetsMVCService.execute("mvcController", { assetId: 1, dataFormat: 'attribute' }),
dataType: 'text',
type: 'post',
success: function (data) {
alert('ok');
},
error: function () {
error.apply(this, arguments);
}
});
assetsMVCService is my wrapper for Angular service. Unfortunately, a product that I am implementing forces me to use AJAX call to get data. Normally, I would use services to get data and then scope for data binding. Is it possible to use a service assigned to the url property in the code above? Interesting enough, I am hitting server with the code above. But something gets wrong on the server.
Thanks
Yes. You could do something like this:
app.service('MVC', function($http) {
var root = 'http://localhost/mvcController';
var queryParams = '?assetid=1&dataformat=attribute';
this.get = function(num) {
return $http.get(root + '/' + num + queryParams);
};
// or if you want to pass the query params in
this.execute = function(assetId, dataFormat) {
return $http.get(root + '?assetId=' + assetId + '&dataFormat=' + dataFormat;
};
// other routes
});
Note that $http can and should be used instead of $.ajax when you're using Angular. It does pretty much the same thing as $.ajax, except it plays nice with Angular.

Passing in parameters to promise.done() after AJAX call

I know there are lots of AJAX questions out there, but after reading through them wasn't able to figure out how to do this (I'm new to JS)
Pass in the $form variable (or other variables) to the ajaxFormSubmitSuccess function, in addition to the "data variable" that gets returned by the ajax call (which you could access by .done(function(data){}); ...not really sure what type of object it is).
I have (this doesn't work):
//handles ajax form submissions
$("form[data-ccajax='true']").submit(ajaxFormSubmit);
var ajaxFormSubmit = function () {
var $form = $(this);
var options = {
url: $form.attr("action"),
type: $form.attr("method"),
context: this,
data: $form.serialize(),
dataType: "html"
};
//send ajax command
var promise = $.ajax(options);
promise.done(ajaxFormSubmitSuccess($form, promise));
promise.fail(ajaxFormSubmitFailure);
return false;
}
Right now the .done(ajaxFormSubmitSuccess($form, promise)); code calls the function below. the data variable doesn't get extracted from promise...so $data remains null throughout the code.
var ajaxFormSubmitSuccess = function ($form, $promise) {
var $data;
$promise.success(function (data) { $data = data; });
alert("succeededajaxFormSubmit");
var target1 = $("#"+$form.attr('data-cctarget1'));
target1.html($data);
}
Any help on how to do this right is much appreciated!
$promise inside the ajaxFormSubmitSuccess is not the result of the ajax call but a promise. It's async so that's why your variable $data is still empty after $promise.success().
Try this way:
var ajaxFormSubmitSuccess = function ($form, $promise)
{
$promise.success(function (data)
{
alert("succeededajaxFormSubmit");
var target1 = $("#"+$form.attr('data-cctarget1'));
target1.html(data);
});
}
For more insights: https://api.jquery.com/promise/

Ajax sent on "keyup" duplicates results when fast typing!

This is my Ajax:
$("form[0] :text").live("keyup", function(event) {
event.preventDefault();
$('.result').remove();
var serchval = $("form[0] :text").val();
if(serchval){
$.ajax({
type: "POST",
url: "<?= site_url('pages/ajax_search') ?>",
data: {company : serchval},
success: function(data) {
var results = (JSON.parse(data));
console.log(results);
if(results[0]){
$.each(results, function(index) {
console.log(results[index].name);
$("#sresults").append("<div class='result'>" + results[index].name + "</div>");
});
}
else {
$("#sresults").append("<div class='result'>לא נמצאו חברות</div>");
}
}
});
}
});
When I type slowly (slower then a letter per second) I get the results correct, when I type faster I get 2 times the same results
example:
slow typing: res1 res2 res3
fast typing: res1 res2 res3 res1 res2 res3
Also, any advice on improving the code would be welcome!
Thats what is happening (pseudocode):
When you're typing slow:
.keyup1
.remove1
//asynchronous ajax1 request takes some time here...
.append1
.keyup2
.remove2
//asynchronous ajax2 request takes some time here...
.append2
When you're typing fast:
.keyup1
.remove1
//asynchronous ajax1 request takes some time here...
//and keyup2 happens before ajax1 is complete
.keyup2
.remove2
.append1
//asynchronous ajax2 request takes some time here...
.append2
//two results were appended _in a row_ - therefore duplicates
To solve duplicates problem, you would want to make your results removing/appending an atomic operation - using .replaceWith.
Build results HTML block first as string and then do the .replaceWith instead of .remove/.append:
var result = '';
for (i in results) {
result += "<div class='result'>" + results[i].name + "</div>";
}
$("#sresults").replaceWith('<div id="sresults">' + result + '</div>');
Another problem (not related to duplicates) may be that older result overwrites newer which arrived earlier (because AJAX is asynchronous and server may issue responses not in the same order it receives requests).
One approach to avoid this is attaching roundtrip marker (kind of "serial number") to each request, and checking it in response:
//this is global counter, you should initialize it on page load, global scope
//it contains latest request "serial number"
var latestRequestNumber = 0;
$.ajax({
type: "POST",
url: "<?= site_url('pages/ajax_search') ?>",
//now we're incrementing latestRequestNumber and sending it along with request
data: {company : serchval, requestNumber: ++latestRequestNumber},
success: function(data) {
var results = (JSON.parse(data));
//server should've put "serial number" from our request to the response (see PHP example below)
//if response is not latest (i.e. other requests were issued already) - drop it
if (results.requestNumber < latestRequestNumber) return;
// ... otherwise, display results from this response ...
}
});
On server side:
function ajax_search() {
$response = array();
//... fill your response with searh results here ...
//and copy request "serial number" into it
$response['requestNumber'] = $_REQUEST['requestNumber'];
echo json_encode($response);
}
Another approach would be to make .ajax() requests synchronous, setting async option to false. However this may temporarily lock the browser while request is active (see docs)
And also you should definitely introduce timeout as algiecas suggests to reduce load on server (this is third issue, not related to duplicates nor to request/response order).
You should involve some timeout before calling ajax. Something like this should work:
var timeoutID;
$("form[0] :text").live("keyup", function(event) {
clearTimeout(timeoutID);
timeoutID = setTimeout(function()
{
$('.result').remove();
var serchval = $("form[0] :text").val();
if(serchval){
$.ajax({
type: "POST",
url: "<?= site_url('pages/ajax_search') ?>",
data: {company : serchval},
success: function(data) {
var results = (JSON.parse(data));
console.log(results);
for (i in results)
{
console.log(results[i].id);
$("#sresults").append("<div class='result'>" + results[i].name + "</div>");
}
}
});
}
}, 1000); //timeout in miliseconds
});
I hope this helps.

jQuery.ajax() sequential calls

Hey. I need some help with jQuery Ajax calls. In javascript I have to generste ajax calls to the controller, which retrieves a value from the model. I am then checking the value that is returned and making further ajax calls if necessary, say if the value reaches a particular threshold I can stop the ajax calls.
This requires ajax calls that need to be processes one after the other. I tried using async:false, but it freezes up the browser and any jQuery changes i make at the frontend are not reflected. Is there any way around this??
Thanks in advance.
You should make the next ajax call after the first one has finished like this for example:
function getResult(value) {
$.ajax({
url: 'server/url',
data: { value: value },
success: function(data) {
getResult(data.newValue);
}
});
}
I used array of steps and callback function to continue executing where async started. Works perfect for me.
var tasks = [];
for(i=0;i<20;i++){
tasks.push(i); //can be replaced with list of steps, url and so on
}
var current = 0;
function doAjax(callback) {
//check to make sure there are more requests to make
if (current < tasks.length -1 ) {
var uploadURL ="http://localhost/someSequentialToDo";
//and
var myData = tasks[current];
current++;
//make the AJAX request with the given data
$.ajax({
type: 'GET',
url : uploadURL,
data: {index: current},
dataType : 'json',
success : function (serverResponse) {
doAjax(callback);
}
});
}
else
{
callback();
console.log("this is end");
}
}
function sth(){
var datum = Date();
doAjax( function(){
console.log(datum); //displays time when ajax started
console.log(Date()); //when ajax finished
});
}
console.log("start");
sth();
In the success callback function, just make another $.ajax request if necessary. (Setting async: false causes the browser to run the request as the same thread as everything else; that's why it freezes up.)
Use a callback function, there are two: success and error.
From the jQuery ajax page:
$.ajax({
url: "test.html",
context: document.body,
success: function(){
// Do processing, call function for next ajax
}
});
A (very) simplified example:
function doAjax() {
// get url and parameters
var myurl = /* somethingsomething */;
$.ajax({
url: myurl,
context: document.body,
success: function(data){
if(data < threshold) {
doAjax();
}
}
});
}
Try using $.when() (available since 1.5) you can have a single callback that triggers once all calls are made, its cleaner and much more elegant. It ends up looking something like this:
$.when($.ajax("/page1.php"), $.ajax("/page2.php")).done(function(a1, a2){
// a1 and a2 are arguments resolved for the page1 and page2 ajax requests, respectively
var jqXHR = a1[2]; /* arguments are [ "success", statusText, jqXHR ] */
alert( jqXHR.responseText )
});

Resources