Ajax never initiating success: when using xhrFields - php

I am having trouble getting the success call to fire in my ajax request. I know the communication is working fine, but the last call in my PHP script, which is a return json_encode($array); will fire as if it is a part of the onprogress object. I would like to "break" the onprogress call and run the success function on the last data sent via return json_encode when the PHP script has terminated...
Here is my AJAX call:
$( document ).ready(function(e) {
var jsonResponse = '', lastResponseLen = false;
$("#btn_search").click(function(e){
var firstname = document.getElementById('firstname').value;
var lastname = document.getElementById('lastname').value;
$.ajax({
type: "POST",
url: 'search.php',
data: $('#search_fields').serialize(),
dataType: "json",
xhrFields: {
onprogress: function(e) {
var thisResponse, response = e.currentTarget.response;
if(lastResponseLen === false) {
thisResponse = response;
lastResponseLen = response.length;
} else {
thisResponse = response.substring(lastResponseLen);
lastResponseLen = response.length;
}
jsonResponse = JSON.parse(thisResponse);
document.getElementById('progress').innerHTML = 'Progress: '+jsonResponse.msg;
}
},
success: function(data) {
console.log('done!');
document.getElementById('progress').innerHTML = 'Complete!';
document.getElementById('results').innerHTML = data;
}
});
e.preventDefault();
});
});
And here is the basic PHP server script:
<?php
function progress_msg($progress, $message){
echo json_encode(array('progress' => $progress, 'msg' => $message));
flush();
ob_flush();
}
$array = array('msg' => 'hello world');
$count = 0;
while($count < 100){
progress_message($count, "working....");
$count += 10;
sleep(2);
}
return json_encode($array);
?>

I made your code work, there were 2 errors. First, in your while loop, your function name is incorrect, try this:
progress_msg($count, "working... ." . $count . "%");
Secondly, the very last line outputs nothing, so technically you don't get a "successful" json return. Change the last line of your server script from:
return json_encode($array);
to:
echo json_encode($array);
UPDATE: Full working code with hacky solution:
Ajax:
$( document ).ready(function(e) {
var jsonResponse = '', lastResponseLen = false;
$("#btn_search").click(function(e){
var firstname = document.getElementById('firstname').value;
var lastname = document.getElementById('lastname').value;
$.ajax({
type: "POST",
url: 'search.php',
data: $('#search_fields').serialize(),
xhrFields: {
onprogress: function(e) {
var thisResponse, response = e.currentTarget.response;
if(lastResponseLen === false) {
thisResponse = response;
lastResponseLen = response.length;
} else {
thisResponse = response.substring(lastResponseLen);
lastResponseLen = response.length;
}
jsonResponse = JSON.parse(thisResponse);
document.getElementById('progress').innerHTML = 'Progress: '+jsonResponse.msg;
}
},
success: function(data) {
console.log('done!');
dataObjects = data.split("{");
finalResult = "{" + dataObjects[dataObjects.length - 1];
jsonResponse = JSON.parse(finalResult);
document.getElementById('progress').innerHTML = 'Complete!';
document.getElementById('results').innerHTML = jsonResponse.msg;
}
});
e.preventDefault();
});
Search.php:
<?php
function progress_msg($progress, $message){
echo json_encode(array('progress' => $progress, 'msg' => $message));
flush();
ob_flush();
}
$array = array('msg' => 'hello world');
$count = 0;
while($count <= 100){
progress_msg($count, "working... " . $count . "%");
$count += 10;
sleep(1);
}
ob_flush();
flush();
ob_end_clean();
echo json_encode($array);
?>
The problem with the "success" method of the ajax call was that it couldn't interpret the returning data as JSON, since the full return was:
{"progress":0,"msg":"working... 0%"}{"progress":10,"msg":"working... 10%"}{"progress":20,"msg":"working... 20%"}{"progress":30,"msg":"working... 30%"}{"progress":40,"msg":"working... 40%"}{"progress":50,"msg":"working... 50%"}{"progress":60,"msg":"working... 60%"}{"progress":70,"msg":"working... 70%"}{"progress":80,"msg":"working... 80%"}{"progress":90,"msg":"working... 90%"}{"progress":100,"msg":"working... 100%"}{"msg":"hello world"}
Which is not a valid JSON object, but multipje JSON objects one after another.
I tried removing all previous output with ob_end_clean(); , but for some reason I can't figure out, it didn't work on my setup. So instead, the hacky solution I came up with was to not treat the return as JSON (by removing the dataType parameter from the AJAX call), and simply split out the final Json element with string operations...
There has got to be a simpler solution to this, but without the use of a third party jQuery library for XHR and Ajax, I couldn't find any.

Related

Ajax sometimes fails to parse the large JSON response

I am calling a PHP service with below ajax code :
jQuery.ajax({
url: 'index.php?option=com_sheet&task=getReportsData',
timeout: 300000,
dataType: "json",
type: "GET",
data: {
'project': projectsStr,
'startweek': startweek,
'endweek': endweek
}
}).done(function(response) {
if (response.success && response.data) {
var projectData = response.data;
if (projectData.projectReportData.length > 0) {
loadDataTable(response.data);
} else {
jQuery('#projectReportData').html("<br/><h2>No Matching Results</h2>");
}
}
}).fail(function(jqXHR, textStatus) {
jQuery(".overlay")[0].style.display = '';
if (textStatus === 'timeout') {
alert('Failed from timeout');
}
alert(textStatus);
});
The php code that provides the response prints the response with :
$data = (object)array_merge(['projectReportData' => $projectReportData]);
header("Content-Type: application/json");
$post_data = json_encode($data, JSON_FORCE_OBJECT);
ob_start('ob_gzhandler');
echo new JResponseJson($data);
ob_end_flush();
jexit();
This ajax works fine sometimes and is able to parse the JSON. But most of the times gives "parsererror".
Below code fetch the data from the DB :
$db = JFactory::getDbo();
$query = "CALL getReportData('" . $startweek . "','" . $endweek . "')";
$db->setQuery($query);
$res = $db->query($query);
$returnArr = [];
$i = 0;
while( $r = $res->fetch_assoc()){
$projectReportData[$i] = $r;
$i++;
}
when i change dataType to text the pointer reaches the .done() but console.log(response) returns a blank.

Continuously get PHP loop data in Ajax Call

I have this codes in process.php:
$users = $_POST['users']; // Sample: "user1, user2, user5"
$users = explode(', ', $users);
$step = 0;
foreach ($users as $r) {
$user_email = get_user_email($r); // Get email of each user
if (!empty($user_email)) {
send_w_mail(); // Send email to each user
$step++;
echo json_encode(
['step' => $step, 'all' => count($users)]
); // echo output
}
}
And this is my ajax call in index.php:
$("#send-message").click(function () {
$.ajax({
url: global_base_url + 'process.php', // global_base_url defined.
async : true,
type: 'POST',
data: {'users': input_users}, // input_users is val() of a input.
encoding: 'UTF-8',
success: function (data) {
data = $.trim(data);
if (data){
data = $.parseJSON(data);
var p_value = parseInt(data.step*100)/data.all;
set_progressbar_value(p_value); // set progressbar value. sample: 23%
}
}
});
});
This codes don't have any problem for execute and showing result.
But I want to Continuously get output json data from process.php in order to show process of each $step in Percent unit in a bootstrap process-bar;
I found some function like ignore_user_abort(), ob_clean() and ob_flush() but don't know how can I solve my problem with them.
How Can I do this? Please help me to solve the problem.
Thanks a lot.
There are two ways of approaching this problem
Websocket
Long polling
I will be describing the long polling method here:
$users = $_POST['users']; // Sample: "user1, user2, user5"
$users = explode(', ', $users);
$step = 0;
foreach ($users as $r) {
$user_email = get_user_email($r); // Get email of each user
if (!empty($user_email)) {
send_w_mail(); // Send email to each user
$step++;
echo json_encode(
['step' => $step, 'all' => count($users)]
); // echo output
//Flush the output to browser
flush();
ob_flush();
}
Jquery does not provide api for XMLHttpRequest.readyState == 3 (Loading docs here) so we need to use raw XMLHttpRequest object
$("#send-message").click(function () {
var prev_response = "";
var xhr = new XMLHttpRequest();
xhr.open("POST", global_base_url + 'process.php', true);
//Send the proper header information along with the request
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {//Call a function when the state changes.
if(xhr.readyState == 3) {
// Partial content loaded. remove the previous response
var partial_response = xhr.responseText.replace(prev_response,"");
prev_response = xhr.responseText;
//parse the data and do your stuff
var data = $.parseJSON(partial_response);
var p_value = parseInt(data.step*100)/data.all;
set_progressbar_value(p_value);
}
else if(xhr.readyState == 4 && xhr.status == 200){
set_progressbar_value(100);
console.log("Completed");
}
}
xhr.send("users="+ input_users);
});

Ajax call doesn't work from iPhone app and arduino

I've created an Arduino project wich sends the coordinates to an URL. The URL does some ajax calls. In the browser it works fine, but when I'm trying it with the Arduino it doesn't work. So I tried to do the same thing with an iOS app, but I got the same problem. This is the code on the page that the Arduino and iOS app request.
var directionsService = new google.maps.DirectionsService();
var base_url = window.location;
var received_data = <?php echo json_encode($received_data); ?>;
$.ajax({
url: 'http://gps-tracker.domain.nl/_api/handler.php',
data: { action: 'post', device_id: received_data['device_id']},
type: 'GET',
dataType:"jsonp",
jsonp:"callback",
success: function (response){
var error = [];
var total = response.length;
for (var type in response) {
if(response[type].types == 'area'){
var x = checkInsideCircle(response[type].longitude, response[type].latitude, received_data['longitude'], received_data['latitude'], response[type].reach / 1000);
if(x == false){
// Outside
error.push(true);
}else{
// Inside
error.push(false);
}
}else if(response[type].types == 'route'){
// Check route
checkOnRoute(response[type].start_latitude, response[type].start_longitude, response[type].end_latitude, response[type].end_longitude, response[type].type, response[type]['reach'], type, function(result) {
error.push(result);
if(error.length == total){
if(error.indexOf(false) >= 0){
// Device is inside route or area
outside = false;
}else{
// Send data to database
$.ajax({
url: 'http://gps-tracker.domain.nl/_api/handler.php',
data: { action: 'post', device_id: received_data['device_id'], longitude: received_data['longitude'], latitude: received_data['latitude']},
type: 'GET',
dataType: 'json',
success: function (response){
console.log('good');
},error: function(jq,status,message) {
alert('A jQuery error has occurred. Status: ' + status + ' - Message: ' + message);
}
});
}
}
});
}
}
},error: function(jq,status,message) {
alert('A jQuery error has occurred. Status: ' + status + ' - Message: ' + message);
}
});
Here is the code from the handler.php file, that the ajax request requests.
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : false;
// Switch actions
switch($action) {
case 'get':
$callback ='callback';
if(isset($_GET['callback'])){
$callback = $_GET['callback'];
}
$routes = ORM::for_table('gps_tracker_route')
->inner_join('gps_tracker_device', array('gps_tracker_device.device_id', '=', 'gps_tracker_route.device_id'))
->where('gps_tracker_route.device_id', $_GET['device_id'])
->where('gps_tracker_device.device_id', $_GET['device_id']);
if($routes = $routes->find_many()){
foreach($routes as $k=>$v){
$v = $v->as_array();
if($v['status'] == 'on' or strtotime(date('Y-m-d H:i:s')) > strtotime($v['start_time']) and strtotime(date('Y-m-d H:i:s')) < strtotime($v['end_time'])){
$response1[$k] = $v;
$response1[$k]['types'] = 'route';
}
}
}
$area = ORM::for_table('gps_tracker_area')
->inner_join('gps_tracker_device', array('gps_tracker_device.device_id', '=', 'gps_tracker_area.device_id'))
->where('gps_tracker_area.device_id', $_GET['device_id'])
->where('gps_tracker_device.device_id', $_GET['device_id']);
if($area = $area->find_many()){
foreach($area as $k=>$v){
$v = $v->as_array();
if($v['status'] == 'on' or strtotime(date('Y-m-d H:i:s')) > strtotime($v['start_time']) and strtotime(date('Y-m-d H:i:s')) < strtotime($v['end_time'])){
$response2[$k] = $v;
$response2[$k]['types'] = 'area';
}
}
}
if(isset($response1) and isset($response2)){
$response = array_merge($response1, $response2);
}elseif(isset($response1)){
$response = $response1;
}else{
$response = $response2;
}
if ( isset($response) ) {
if ( is_array($response) ) {
if (function_exists('json_encode')) {
header('Content-Type: application/json');
echo $callback.'(' . json_encode($response) . ')';
} else {
include( ABSOLUTE_PATH . '/classes/json.class.php');
$json = new Services_JSON();
echo $json->encode($response);
}
} else {
echo $response;
}
exit(0);
}else{
exit();
}
break;
case 'post':
$_GET['timestamp'] = date("Y-m-d H:i:s");
$record = ORM::for_table('gps_tracker_device_logging')->create($_GET);
$record->save();
$item = ORM::for_table('gps_tracker_device_logging')
->where('id', $record->id);
if($item = $item->find_one()){
$item = $item->as_array();
echo json_encode($item);
}
break;
default:
die('invalid call');
}
Can someone help me?
EDIT
I think it is something with Javascript. I don't know if it's possible to use javascript when a device, like Arduino, makes a http request to a server. Someone know?
I think that it's because you need a Web Browser that supports JavaScript.
I don't work with Arduino, but from what I know it does not have a "real" Web Browser - it can only pull/download data but can't execute the JS part.
For JS to work you need something to run it. That is why it works in a the browser.

How to pass mysql result as jSON via ajax

I'm not sure how to pass the result of mysql query into html page via ajax JSON.
ajax2.php
$statement = $pdo - > prepare("SELECT * FROM posts WHERE subid IN (:key2) AND Poscode=:postcode2");
$statement - > execute(array(':key2' => $key2, ':postcode2' => $postcode));
// $row = $statement->fetchAll(PDO::FETCH_ASSOC);
while ($row = $statement - > fetch()) {
echo $row['Name']; //How to show this in the html page?
echo $row['PostUUID']; //How to show this in the html page?
$row2[] = $row;
}
echo json_encode($row2);
How to pass the above query result to display in the html page via ajax below?
my ajax
$("form").on("submit", function () {
var data = {
"action": "test"
};
data = $(this).serialize() + "&" + $.param(data);
$.ajax({
type: "POST",
dataType: "json",
url: "ajax2.php", //Relative or absolute path to response.php file
data: data,
success: function (data) {
//how to retrieve the php mysql result here?
console.log(data); // this shows nothing in console,I wonder why?
}
});
return false;
});
Your json encoding should be like that :
$json = array();
while( $row = $statement->fetch()) {
array_push($json, array($row['Name'], $row['PostUUID']));
}
header('Content-Type: application/json');
echo json_encode($json);
And in your javascript part, you don't have to do anything to get back your data, it is stored in data var from success function.
You can just display it and do whatever you want on your webpage with it
header('Content-Type: application/json');
$row2 = array();
$result = array();
$statement = $pdo->prepare("SELECT * FROM posts WHERE subid IN (:key2) AND Poscode=:postcode2");
$statement->execute(array(':key2' => $key2,':postcode2'=>$postcode));
// $row = $statement->fetchAll(PDO::FETCH_ASSOC);
while( $row = $statement->fetch())
{
echo $row['Name'];//How to show this in the html page?
echo $row['PostUUID'];//How to show this in the html page?
$row2[]=$row;
}
if(!empty($row2)){
$result['type'] = "success";
$result['data'] = $row2;
}else{
$result['type'] = "error";
$result['data'] = "No result found";
}
echo json_encode($row2);
and in your script:
$("form").on("submit",function() {
var data = {
"action": "test"
};
data = $(this).serialize() + "&" + $.param(data);
$.ajax({
type: "POST",
dataType: "json",
url: "ajax2.php", //Relative or absolute path to response.php file
data: data,
success: function(data) {
console.log(data);
if(data.type == "success"){
for(var i=0;i<data.data.length;i++){
//// and here you can get your values //
var db_data = data.data[i];
console.log("name -- >" +db_data.Name );
console.log("name -- >" +db_data.PostUUID);
}
}
if(data.type == "error"){
alert(data.data);
}
}
});
return false;
});
In ajax success function you can use JSON.parse (data) to display JSON data.
Here is an example :
Parse JSON in JavaScript?
you can save json encoded string into array and then pass it's value to javascript.
Refer below code.
<?php
// your PHP code
$jsonData = json_encode($row2); ?>
Your JavaScript code
var data = '<?php echo $jsonData; ?>';
Now data variable has all JSON data, now you can move ahead with your code, just remove below line
data = $(this).serialize() + "&" + $.param(data);
it's not needed as data variable is string.
And in your ajax2.php file you can get this through
json_decode($_REQUEST['data'])
I would just..
$rows = $statement->fetchAll(FETCH_ASSOC);
header("content-type: application/json");
echo json_encode($rows);
then at javascript side:
xhr.addEventListener("readystatechange",function(ev){
//...
var data=JSON.parse(xhr.responseText);
var span=null;
var i=0;
for(;i<data.length;++i){span=document.createElement("span");span.textContent=data[i]["name"];div.appendChild(span);/*...*/}
}
(Don't rely on web browsers parsing it for you in .response because of the application/json header, it differs between browsers... do it manually with responseText);

How get AJAX to Post JSON data into div

I'm new Jquery and AJAX and I've really been struggling with the syntax I've been trying to use other tutorials as reference but nothing seems to work. I feel I have the right idea but syntax is wrong somewhere please help.
Here is the Ajax side
var var_numdatacheck = <?php echo $datacheck; ?>;
var var_numcheck = parseInt(var_numdatacheck);
function activitycheck(){
$.ajax({
type: 'POST',
url: 'feedupdate.php',
data: {function: '3test', datacheck: var_numcheck},
dataType: "json",
success: function(data) {
var json = eval('(' + data + ')');
$('#datacheck').html(json['0']);
var var_numcheck = parseInt(msg);
//setTimeout('activitycheck()',1000)},
error:function(msg) {
console.log(msg);
}
});
}
$(document).ready(function() {
activitycheck();
});
Here is the php the AJAX calls
<?php
require "dbc.php";
$function = $_POST['function'];
$datacheck = $_POST['datacheck'];
$search="SELECT * FROM Feedtest ORDER BY id DESC";
$request = mysql_query($search);
$update= mysql_fetch_array($request);
$updateid = $update['id'];
$updatecheck = mysql_num_rows($request);
$data = array();
if ($function == $datacheck){
echo $updatecheck;
echo $datacheck;
}
if ($function == "3test" && $updatecheck > $datacheck ) {
$updatesearch="SELECT * FROM Feedtest WHERE id = '$updateid' ORDER BY id DESC";
$updatequery = mysql_query($updatesearch);
$data['id'] = $updateid;
while ($row = mysql_fetch_array($updatequery))
{
?>
<?php $data[]= $row['First Name']; ?>
<?php
}
echo json_encode($data);
}
?>
</div>
</ul>
first of all ,always use JSON.parse(data) instead of eval.It is considereda a good practice.
second thing is always try to debug your code by checking it in console or alerting.In your context,this is what is happening-:
$.ajax({
type: 'POST',
url: 'feedupdate.php',
data: {function: '3test', datacheck: var_numcheck},
dataType: "json",
success: function(data) {
var data = eval('(' + data + ')');
console.log("myData"+data)//debugging.check the pattern so that you can acces it the way you want!!!
for(var i=0;i< data.length;i++)
{
alldata += "<li>"+data[i][0]+"<li><hr>";
}
$('#datacheck').html(alldata);
});
}
For JSON.parse:
success: function(data) {
var data = JSON.parse(data);
console.log("myData"+data)//debugging.check the pattern so that you can acces it the way you want!!!
for(var i in data)
{
alldata += "<li>"+data[i].First Name+"<li><hr>";
}
$('#datacheck').html(alldata);
});

Categories