I am pretty new to web programming, so please bear with me.
I created a web page that submits form data to a PHP exec() function. This function requests data (once or multiple times) from a website, manipulates it in various ways, and sticks it in a file on my web server. While processing, a loader .gif file appears on the web page. I have created a piece of JavaScript code to handle the process waiting period, but I'm not sure that I'm doing it right. The script is as follows:
<script>
window.set = 0;
window.uid = '';
document.forms[0].onsubmit = function(e)
{
console.log($(this).serialize());
e.preventDefault();
e.stopPropagation();
// Display "Waiting" .gif during processing
$('#loader').show();
// Perform data submission once (when window.set = 0). After that,
// keep waiting for output and manifest file to be created. Call
// "fetch" function repeatedly to test for completion. When completed,
// call clearInterval to stop processing.
window.int_ = setInterval(function()
{
$.ajax({
"url": "./",
"type": "POST",
"data": !window.set ?$("#form").serialize() : { 'fetch': 1, 'uid': window.uid }}).done(function(data)
{
var d = data = JSON.parse(data);
if (!window.set)
{
window.uid = d.uid;
window.set = 1;
return;
}
if (data.status === 'ok')
{
document.location.replace(data.href);
data.manifest = data.manifest.replace(/\./g, ".<br />");
$('#manifest').show();
$('#manifest').html("<b>Results from run:</b> <br />" + data.manifest);
$('#loader').hide();
window.set = 0;
window.uid = '';
clearInterval(window.int_);
}
else
{
// waiting
}
});
}, 100);
}
</script>
The code for the "fetch" function referenced in the first AJAX call is as follows:
if ($_POST['fetch'])
{
$uid = $_POST['uid'];
/* check for availability*/
if (is_file(realpath("./$uid")))
{
$f = file_get_contents($uid);
$m = file_get_contents("./$uid.manifest");
}
else
{
$f = "";
}
if ($f != "")
{
echo json_encode(array("status" => "ok", "href" => $f, "manifest" => $m));
die();
}
else
{
echo json_encode(array("status" => "err", "href" => $f));
die();
}
}
What I'm trying to do here is perform the external website processing/manipulation one time, while waiting for the processing to be finished. The "fetch" function checks to see if my output file has been created. If it has, processing ends.
Is this a programmatically sound approach to this problem? Are there alternatives that would be much better?
I would greatly appreciate any insight you can provide. I really want to learn the right way to do things.
I try to make an easy explain of HTTP Requests...
At first you have your Backend code on a Webserver, in your case written in php. This Script doesnt do anything else, then process the data you send to it and maybe post (echo) a failure, or succeed of its processing back to the frontend client. In your case thats all.
On Frontend side its almost the same procedure, whatever language or device you take.
You invoke a HTTP POST or GET request in an asynchronous task, in your case jQuery does that for you by calling its $.ajax function to your php.
Also in that request, you define a callback function which will be invoked automatically, after async processing is finished. jQuery does that for you too, its the .done() function right after the $.ajax.
To indicate loading, the best way would be to Show your loading image right before the $.ajax line of code... And hide or remove it inside the .done() function... To indicate loading is done...
Thats all.
Related
Is it possible to use Ajax, Jquery or Javascript to call a specific PHP Function and refresh / reload it every 10 seconds for example inside a specific Div or areas?
Connection.php
function TerminalStatus ($IPAddress, $portStatus ) // Responsible for current terminal status
{
$connectStatus = fsockopen($IPAddress, $portStatus, $errno, $errstr, 10); // Build cconnection to Terminal socket 25001
if (!$connectStatus) {
echo "$errstr ($errno)<br />\n";
} else {
$Status = fgets($connectStatus) ;
echo $Status ();
}
}
This connection is just to see the current status of a terminal.
I want to see the status of this function at the bottom of my index.php without refreshing the whole page.
I can accomplish this by putting this function in its own PHP Files (status.php) and using Javascript in the following way:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
<script type="text/javascript">
var auto_refresh = setInterval(
function ()
{
$('#Status').load('status.php');
}, 1000); // refresh every 1000 milliseconds
</script>
But i just want to utilise the function instead.
Is this possible?
The solution you have already is the correct way to do this: the JavaScript fetches a URL, and that URL renders the appropriate piece of content.
It's important to remember that, as far as the web browser is concerned, PHP doesn't exist. Any request from the browser - whether you've typed in a URL, followed a link, submitted a form, made an AJAX request, etc - is just a message to some remote server for a particular URL, perhaps along with some extra headers and body data. When the server receives that request, it can do whatever it likes to generate a response to the browser.
So when you write $('#Status').load('status.php');, the browser is sending a request to the server, which happens to be configured to execute the PHP script status.php. You can then do what you like in PHP to produce the response - but there is no direct link between a request and a PHP function.
However, as others have pointed out, you don't have to create a new PHP file for every piece of behaviour you want, because inside the PHP code you can check things like:
the query string parameters, in $_GET
submitted form data, in $_POST
the HTTP headers from the request
These can be set by your JavaScript code to whatever you like, so you could for instance write $('#Status').load('index.php?view=statusonly'); and then at the top of index.php have code like this:
if ( $_GET['view'] === 'statusonly'] ) {
echo get_status();
exit;
}
How you arrange this is entirely up to you, and that's what programming is all about 🙂
That's impossible to do this operation just with the PHP function.
you should use javascript as you use that or use socket in javascript to connect you status.php and update without refresh the whole page.
I'm not sure if i understood the problem but you can use AJAX to execute specific function. Something like this:
First build your ajax:
$.ajax({
type: "POST",
url: "URL_TO_PHP_FILE",
data: "refreshStatus", // this will call the function
success: function(status){
$('#Status').text(status); // this will load the info you echo
},
});
Since you want to do it every second - wrap the whole thing with interval (i use your code from the question):
var auto_refresh = setInterval( function () {
$.ajax({
type: "POST",
url: "URL_TO_PHP_FILE",
data: "refreshStatus",
success: function(status){
$('#Status').text(status);
},
});
}, 1000);
Then, on you PHP_FILE add condition the execute the specific function when POST been done:
if ($_SERVER["REQUEST_METHOD"] == "POST" && $_POST['refreshStatus']) {
// run this code
}
Is that what you aimed to achieve?
jQuery::load() supports fragment identifiers. So you can just load the part that you want to replace:
$( "#Status" ).load( "status.php #PartId" );
This will load the HTML output of the script and extract the part. The PHP script will run completely - the rest of the HTML output will be thrown away on the JS side.
I am wondering is it a good practice to make an ajax in an ajax callback function (could be called nested ajax calls?) ? Anyway here is my example
ajax.js
$(document).ready(function() {
$('#button').click(function() {
var string = 'some string';
$.post('ajax-call.php',
{
string: string
}, function(result) {
if(result == 'success') {
// Second ajax call if result returned is success
$.post('second-ajax.php',
{
variable: 'Some Variable'
}, function(second_result) {
if(second_result == 'yes') {
// Do some thing when the second result returned 'yes'
} else {
// Alert error or something
}
});
} else {
// If first result is not success, show a message
}
});
});
});
So basically I have two separate php file that is called on different time, if the first ajax call returned 'success' then proceed to call the second ajax call. Or should I be using one ajax call, one php script, and decide what to do depending on the result of callback ? example below.
ajax2.js
$(document).ready(function() {
$('#button').click(function() {
var string = 'some string';
$.post('ajax-call.php',
{
string: string
}, function(result) {
if(result == 'success') {
// Do something
} else if(result == 'unsuccessful') {
// If first result is not success, show a message
} else {
// Show error message
}
});
});
});
*Note: both php script are quite a heavy and long script which the first script is codes for validating the ajax call, and if everything is validated correctly, proceed to second ajax call to process the datas into database and so on. The first example will make the script much cleaner and neater, but I am wondering if it is good practice to use nested ajax like that ?
All suggestions and comments are greatly welcome. Thank you in advance for enlightening me on this.
Answering the question:
If both ajax calls are two different services and the second call depends on the first response, I'll do it.
If they are standalone services, I'll work with promises and do the callback when both are resolved.
Maybe is not focused on the question itself, but I see weird to make two server calls for just one real action (the second one).
What I'll do is to make just one call. If the validation doesn't pass, return the error. If it passes, call the other php on the server side and return a vlid response to the client.
Server should do the same job, but you save one data transmission from client to server.
That's just an opinion. I hope it helped you.
I have a function in file do.php like this:
<?php
if(isset($POST['submit']))
{
for($i=0;$i=10;$i++)
{
$reponse = array(
'content' = > "This is an example - process #" . $i;
);
echo json_encode($response);
sleep(1); // sleep one second each loop
}
}
?>
and I have some short JQUERY codes use ajax to post data...
<button onclick="post()">Submit</button>
function post()
{
$.ajax({
type: "POST",
url: "do.php",
data: data,
success: function (data){
var json = jQuery.parseJSON(data);
$('#result').html(json.content);
}
});
}
and this is the output...
This is an example - process #1
This is an example - process #2
This is an example - process #3
....
When I click on Submit button, I can see a request on firebug run 10 seconds to finish and show the result. Now I want each result showed line by line when it finish in the while loop. I can build a websocket system but this system take very much my times and to big system, I just need a simple way to do this if possible.
I still try to save output in to txt file and use JQUERY read it every 500ms but this way take too much request and it doesn't work well.
What are you trying to achieve ?
From what I understand you try to execute several processes in SERVER side, and you want, from CLIENT side, to query their status(which process is still running/finished...)
If so, IMO you can execute those processes(using fork() or whatever), and let the parent process to return a list of unique token identifier for each process, to your AJAX request.
Now for every 500ms, using setInterval(), query the of the tokens your received.
Hope it help a bit.
I have built an uploader for my application but struggling on something.
Every 3 seconds my AJAX script makes a call to my ASP page, checkProgress.asp, to check how many files are in that folder during upload, it also checks if a txt file called complete.txt is in there.
When the count is done, it sends a response back to the AJAX script with something like "File 2 uploaded..." and 3 seconds later it will send "File 3 uploaded...", and so on. If the complete.txt file was found, it would return "Complete" instead of counting. This worked fine, once, and then didn't seem to perform properly after that. I get the "complete" message as I should but not getting the file count progress response.
I ran the checkProgress page manually with a new browser window to see why my progress panel was not updating with the progress, and noticed that the browser loading icon was just spinning, and when the upload finished, "Complete" popped up. So the AJAX call wasn't reaching the page to gather the count of files because it was busy, which confuses me, because all that page is doing is counting how many files are in a folder.
Can somebody suggest what I'm doing wrong? Is this just simply not going to happen while that folder is being added to?
Here is my AJAX script. This starts when the upload starts:
var upload1ProgressCheckInt = setInterval(function() {
var postData = "token="+token;
$.ajaxSetup ({ cache: false });
$.ajax({ type : 'GET', url : 'ajax/checkProgress.asp',
dataType : 'html', data : postData,
success : function(data) {
if (data == "Failed") {
$('#upload1ProgressStatus').html('Error: Upload cancelled!');
clearInterval(upload1ProgressCheckInt);
// do stuff
} else if (data == "Complete") {
$('#upload1ProgressStatus').html('Success: Files uploaded');
clearInterval(upload1ProgressCheckInt);
// do stuff
} else {
$('#upload1ProgressStatus').html(data);
}
}
}); // end ajax
}, 3000);
and this the checkProgress.asp page:
Set FSO = Server.CreateObject("Scripting.FileSystemObject")
If (FSO.FileExists(Server.MapPath("../files/photos/"&token_&"/complete.txt"))) = True Then
Response.Write "Complete"
Else
Set folder = FSO.GetFolder(Server.MapPath("../files/photos/"&token_&"/"))
Set files = folder.Files
fileCounter = files.Count
Response.Write "File "&fileCounter&" uploaded..."
End If
...continuing from comments.
So here is how I understand it. Classic ASP assigns a worker thread to each session, because Classic ASP object are single threaded, and thus the only way to share them (stored in the Session object) between requests is to have a single thread for each session. Naturally that means exactly what you are seeing - all other requests are blocked until upload finishes.
Way to work around that would be to break out of the session. Unfortunately session cookie is HTTP-only (for security reasons), so I don't think there is a way to drop it from AJAX request.
You could make your IIS entry respond to another hostname and convert your AJAX request into JSONP request to that second hostname. I am not sure if there is a more graceful way to do it.
==================
EDIT: Actually I take back the part about cookies. Surely you can kill them by giving headers:{Cookie:""} to your ajax() call? Worth a try....
I'm trying to send a form with mootools and depending on the response from the php script do such or such thing. The thing is I fail to be able to use conditional statements inside of the onComplete part of the code.
I'm missing something really obvious probably, please help me :)
$('formName').addEvent('submit', function(e){
e.stop();
var req = new Request.HTML({
url : 'phpUrl.php',
data : $('formName'),
update : $('modify-me'),
onComplete: function(){
$('formName').reset();
if($('modify-me').get('text') = "1"){
alert("succeed");
}else{
alert("failure");
}
}
}).send();
});
This was my lame attempt to use the php response in the code, but of course it didn't work.
Needless to say I'm new to all this asynchronous client-server communication stuff, but I'm really intrigued by it.
You are assigning in your if statement (single =), not checking equality (==). Change the line
if($('modify-me').get('text') = "1")
to
if($('modify-me').get('text') == "1")
Sorry guys, maybe I'm late... I'm working on Mootools 1.2.4 for the client side and on PHP for the backend. This is the way I submit forms and get response from the server...
$('myFormID').set('send', {
noCache: true,
onRequest: function(){
// show some rotating loader gif...
},
onComplete: function(response) {
// hide the loader gif...
objJson = JSON.decode(response);
if(objJson.success){
// do your success stuff...
alert(objJson.msg);
} else {
alert(objJson.msg);
}
},
onFailure: function(){
alert("Request Aborted.");
}
}).send();
In my case the form submit is triggered by a button, but could be whatever... let's look at the server side (I use PHP but any other language is good)
if($somethingWentWrong){
echo json_encode(array("success" => false, "msg" => "Check your form."));
} else {
echo json_encode(array("success" => true, "msg" => "Data saved."));
}
after all the server-side checks and validations (and maybe an Update on a MySql batabase) I just return a Json array (that's whay I have a JSON.decode(response) on the client-side-earth) and then just check the "success" key to discover if the submitting succeded on the server-side-moon. I just add a small message that I display in an alert. Obviously I could use the JSON array to send back a lot more data to the client, but in this case is enough. Hope this helps and please let me know of better solutions.