As we all know, the php script is executed on the server side and after it is processed it is given to the client. You can specify in the server settings - display information to the client as information is output, but this is an unacceptable setting. I also learned that with the help of web sockets, you can establish a direct client-server connection and, therefore, see the result of the program, only the output will be incomprehensible as information arrives or after the entire script has been completed on the server side. It is also not clear how to draw a progress bar on the client side. The easiest is a div with a background and how to add css on the fly. Can use ajax and peck the database every second. Explain how it is implemented. Or it may be necessary to examine the documentation on HTTP and transfer some information in the header. In general, I do not understand where to start digging.
- I don't understand how these ajax requests can help me? First I need to contact one php script, find out its readiness and notify the client about it, and ajax can respond only when the server has executed the script. And secondly, even if I want to find out in a second how the execution status of the php script has changed, ajax will go and launch a new php script and I don’t need to do that at all - Mcile
- You can write the server part to js using Node.js + a reactive framework for dynamically changing content on the front, then there are no problems at all in progress bars and things like that - nueq
- The main question is still not clear - how to show the client through the progress bar about% execution of the php script. - Mcile
2 answers
Here you have a simple progress bar made on the knee
jQuery(document).ready(function($) { var setProgress = function(ABar, AVal) { var width = ABar.width(); var margin = width - width * AVal / 100; $('.progress', ABar).css({'margin-right': margin}); $('.val', ABar).text(AVal); }; var percent = 0; setProgress($('#bar'), percent); var interval = setInterval(function() { percent++; setProgress($('#bar'), percent); if (percent >= 100) clearInterval(interval); }, 100 ); }); #bar { background-color: grey; width: 150px; } .progress { background-color: blue; color: white; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="bar"> <div class="progress"> <span class="val">0</span>% </div> </div> - excellent implementation! - now it remains to understand the fact that the data we have come from the server, and not ticking every 100 milliseconds and how to understand the server executed 50% of the PHP script for example. For example, the parser runs for 15 minutes, but of course it may also be less than that. As a rule, I heard that NodeJS should be used for this implementation and that it is better not to use php to implement the progressbar on the client side. The main question is still not clear - how to show the client through the progress bar about% execution of the php script. I read about the creation of the demon and the set of parallel processes, about multithreaded realizations - Mcile
- poke me like a kitten in the documentation, I do not know where to dig - Mcile
- Maybe you will be helped by expange.ru/e/… (increase in the running time of the php script). + I also remember there was a command to output html to the client directly during the execution of the script, but I don’t remember it (if echo cannot try print but note that print without a special buffer and it will always be displayed first than any echo) - Denis Kotlyarov
- But all this is not a good idea. Uploading files can be used html fitchami (they are well associated with php and you get variables). And so js in client business. - Denis Kotlyarov
There are progress bars (all of them are executed on the client side), which work when uploading a file to the server and back in the case when we send a file or accept, you can see such progress bars in CMS WordPress their principle - access to browser resources.
My progress bar, like many, performs some actions on the server based on the data received from the client, either by a command from the user starts a long process - suppose parsing 2,000,000 pages. If all this was done in 1 pass, then for this it would be necessary to allocate a few weeks to the work of the script and, as a rule, would end up with an error. Since we can have regular hosting with standard server settings, in which we cannot climb, we will have to implement the code with interruptions, and since the script can run for weeks, the sessions will not work because there is no possibility to keep the browser window open for several weeks . The case when the same application is running on different computers is not considered, because our application needs all server resources.
On the client side, we must use the button to start recursive spaghetti code, using only ajax.
<!DOCTYPE HTML> <html> <head> <title>Процесс обновления базы</title> <link rel="stylesheet" type="text/css" href="v/css/style.css"> <script src="v/js/jquery-3.1.1.min.js"></script> </head> <body> <main class="main"> <div class="container"> <div id="preloader"> <div id="progress"></div> <div id="progress_info"><span class="procent">0</span>% Примерно осталось <span class="time">...</span></div> </div> <div id="go">Запуск!</div> </div> </main> </body> </html> <script> var go=true,goods_count=0,size=0,i=10,start=+new Date(),end_start=+new Date(),mid=0; $.post('c/post.php',{'act':'distance_count'},function(reply){i=reply;console.log(reply);}); function load(cur_i){ $.ajax({ type: "POST", url: "distance.php", data: {'i':i}, success: function(reply){ console.log(reply); i++; $('.procent').text(Math.floor(i/size*100)); $('#progress').css({'width':Math.floor(i/size*100)+'%'}); if(!mid) mid=+new Date()-start; else mid=(mid*i+new Date()-start)/(i+1); //end_start=(+new Date()-start)*(size-i)/1000; end_start=+mid*(size-i)/1000; if(end_start<60) $('.time').text(Math.floor(end_start)+' c'); else if(end_start/60<60){ $('.time').text(Math.floor(end_start/60)+' мин.'+Math.floor(end_start%60)+' c'); } else if(end_start/60/60<24) { $('.time').text(Math.floor(end_start/60/60)+' часов'+Math.floor(end_start%60)+' мин.'); } else { $('.time').text(Math.floor(end_start/60/60/24)+' дней'+Math.floor(end_start/60/60%24)+' часов'); } start=+new Date(); if(i<size)load(i); else $('#progress_info').html('выполнено'); }, error: function(){ start=+new Date(); load(i); } }); } $('#go').click(function(){ if(go){ go=false; $('#progress_info').fadeIn(); $.post('c/post.php',{'act':'places_count'},function(reply){ goods_count=+reply; size=goods_count*10; //size=5; start=+new Date(); load(i); }); } }); </script> Here is a special example, but I used this principle in other tasks. The most basic thing to see here is first.
var go=true,goods_count=0,size=0,i=10,start=+new Date(),end_start=+new Date(),mid=0; $.post('c/post.php',{'act':'distance_count'},function(reply){i=reply;console.log(reply);}); Here we will learn from the server how many passes we have already done and write to the variable i. By clicking on the start button of the parser, we need to find out how many passes we actually do.
$('#go').click(function(){ if(go){ go=false; $('#progress_info').fadeIn(); $.post('c/post.php',{'act':'places_count'},function(reply){ goods_count=+reply; size=goods_count*10; //size=5; start=+new Date(); load(i); }); } }); We protected ourselves from re-clicking on the launch by translating go = false; Highlight the panel about the calculation of the remaining time $ ('# progress_info'). FadeIn (); Requested from the server from the file c / post.php the number of passes and recorded it in the variable size = goods_count * 10; In your case, this will most likely be size = goods_count;
Denote the load time start = + new Date (); - it will help us to calculate the time interval for working out the script (I chose experimentally - this is indicated by the signed line // size = 5; that it is enough for me to run the script in a duration of 25-45 seconds, suppose 450 products in one call to the server) and run our recursive load (i) function; which we pass the only parameter - at what stage we are. The task of this function will include:
- Send the current status to the server (for example, 3000) Catching the number 3000, the server will understand that 3000 times the cycle has already been completed and that you should not start again, but go directly to 3000, 3001, 3002 ...
- Must receive a response from the server, no matter what with or without error
- Act differently if the answer is successful and if the answer is unsuccessful.
function load(cur_i){ $.ajax({ type: "POST", url: "distance.php", data: {'i':i}, success: function(reply){ i++; start=+new Date(); if(i<size)load(i); else $('#progress_info').html('выполнено'); }, error: function(){ start=+new Date(); load(i); } }); } if successful, we add a unit to the counter, check whether we have reached the goal, if not - go to it if the error is on the server - then we rerun
I somehow first tried to implement it as follows
for(var i=0;i<size;i++){ $.post('c/do.php',{'i':i},function(reply){ //какая то информация для прогресс бара }); } but got horrified - my progress bar galloped. It turns out that the java script shot the whole cycle in a second and then I received answers from a breathless server, it’s good that I set a limit for size
As for the appearance of the progress bar - then everyone can have it. You need to store the subtotals in the database, at least in a file. There will be questions - write.
- and as for the code on the server, it was the same, only the queries to the database changed depending on the i parameter, and the code itself wrote to the database. Since the code was writing to the database, let us say, let us say in the morning parser $ .post ('c / post.php', {'act': 'distance_count'}, function (reply) {i = reply; console.log (reply); }); referring to the database gave the updated data. - Mcile