文档章节

PHP实现前台同步显示后台任务进度

mickelfeng
 mickelfeng
发布于 2013/07/17 13:14
字数 860
阅读 1055
收藏 14

这两天需要给公司开发一个短信发送提醒的功能,一次批量发送几千条短信。
如果直接在后台循环执行虽然可行,但是前台操作用户就只能坐着空等,完全看不到后台执行结果,所以考虑能不能有一种办法可以在php后台执行过程中同时在前台显示后台执行任务进度呢。
但是这里遇到一个问题,一般情况下php都是在后台任务执行完毕后输出结果到浏览器,在执行过程不会给浏览器发送任何数据。这个时候想到了可以使用php的flush函数,可以使用flush函数在程序执行中强制输出;
尝试以下代码:

<?php
for($i= 1;$i<= 50;$i++) {
 ob_flush();
 flush();
 echo$i.'<br/>';
 sleep(rand(0, 1));
}
?>

网上大都这样的例子,看代码应该会每隔一秒输出一个数字。但是大家实际测试下情况并非如此,而是和没用flush一样,一次性输出1-50;
在这里请大家参考下鸟哥博客上的一篇文章http://www.laruence.com/2010/04/15/1414.html( 深入理解ob_flush和flush的区别);
其中有一段话:

有些Apache的模块,比如mod_gzip,可能自己进行输出缓存,这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。 

甚至浏览器也会在显示之前,缓存接收到的内容。例如 Netscape浏览器会在接受到换行或 html 标记的开头之前缓存内容,并且在接受到 </table> 标记之前,不会显示出整个表格。 

一些版本的 Microsoft Internet Explorer 只有当接受到的256个字节以后才开始显示该页面,所以必须发送一些额外的空格来让这
些浏览器显示页面内容。

所以找到问题所在了,不是因为flush没有起作用,而是服务器或者浏览器在内容不到一定的字节数(甚至是没有遇到html标记)同样会进行缓存,找到问题所在后尝试以下代码;

<?php
echostr_repeat("<b></br>",4096);//随便输出一段代码立即输出
for($i= 1;$i<= 50;$i++) {
ob_flush();
flush();
echo$i.'<br/>';
sleep(rand(0, 1));
}
?>

已经可以将后台数据实时发送到前台了,然后有办法了吗?结合js,每次循环都输出一段js,去操作html节点;附上disucz中提出出来的安装进度代码供大家参考吧

<html xmlns="http://www.w3.org/1999/xhtml"><head>
<meta content="text/html; charset=utf-8"http-equiv="Content-Type">
<title>Discuz! 安装向导</title>
<style type="text/css">
body{ padding:5px 0; background:#FFF; text-align:center; }
body, td, input, textarea, select, button{ color:#666; font:12px/1.5 Verdana, Tahoma, Arial,'Microsoft Yahei','Simsun', sans-serif; }
.container{ overflow:hidden; margin:0 auto; width:700px; height:auto !important;text-align:left; border:1px solid #B5CFD9; }
.main{ padding:20px 20px 0; background:#F7FBFE url(bg_repx.gif) repeat-x 0 -194px; }
    .main h3{ margin:10px auto; width:75%; color:#6CA1B4; font-weight:700; }
#notice { overflow: hidden; margin: 20px; padding: 5px; height: 300px; border: 1px solid #B5CFD9; text-align: left; }
</style>
<meta name="Copyright"content="Comsenz Inc.">
</head>
<body><div>
<div><script type="text/javascript">
functionshowmessage(message) {
    document.getElementById('notice').innerHTML += message +'<br/>';
    document.getElementById('notice').scrollTop = 100000000;
}
</script>
        <div id="notice"></div>
<?php
//检测完成后显示的信息
functionshowjsmessage($message) {
    echo'<script type="text/javascript">showmessage(\''.addslashes($message).' \');</script>'."\r\n";
    flush();
    ob_flush();
}
 
//模拟初始化数据表
for($i= 1;$i<= 50;$i++) {
    showjsmessage("建立数据表 {$i} ... 成功");
    sleep(rand(0, 1));
}
 
?>
</div>
</div>
</body>
</html>

本文转载自:

mickelfeng

mickelfeng

粉丝 237
博文 2802
码字总数 604377
作品 0
成都
高级程序员
私信 提问
加载中

评论(4)

lazyphp
lazyphp
这个不错!原来哪些安装过程就是这样实现的
ChpiTer
ChpiTer
mark
mickelfeng
mickelfeng 博主
调用接口发,这个需要付费
一只囧蟹
一只囧蟹
PHP下用什么发短信
asyncTask详解

介绍 android UI是线程不安全的,因此想实现在子线程中刷新UI就需要借助一些机制来实现,一般有两种方法:handler+message;还有一种就是今天我们要讲的asyncTask。asyncTask相对handler+mes...

tomcater
2016/04/19
48
0
ajax+php实现进度显示是怎么实现的

如题,比如我后台要循环一百次,在前台需要一个进度条,实时的显示循环的进度,这个用php是怎么实现的,请教各位大神,谢谢! 实时的进度显示,是在当前脚本执行中,比如上面说的循环100次,...

王昊然
2012/10/18
1K
5
ios 流媒体播放器实现流程及FreeStreamer的使用

简介 最近实现了一个流媒体播放器,使用的是FreeStreamer库,至于为什么不用avaudioplayer或者avplayer,前一个是不能播放网络音乐,后一个则是体验不好,缓存不够会暂停,然后又要手动播放。...

cfxiaoxixi
2018/01/01
0
0
Background Task & Multitask (后台任务和多任务处理)

概述 为了确保创建一个快速响应的用户体验以及为了优化手机上的电源使用,在 Windows Phone 中,仅允许在前台运行一个应用。然而,Windows Phone 中的若干功能为应用在不是活跃的前台应用时提...

失足处男的倒霉孩子
2013/12/27
1K
0
Android上传文件到Web服务器,PHP接收文件(二)

接上一篇文章《Android上传文件到Web服务器,PHP接收文件(一)》,这次在之前的基础上添加进度显示,Java代码如下所示: package com.lenovo.uptest; import java.io.DataInputStream;impo...

一别经年
2014/01/20
140
0

没有更多内容

加载失败,请刷新页面

加载更多

移动深度学习:人工智能的深水区

人工智能技术经历6年的快速发展,重新定义了很多行业的用户体验,而这仅是开始。 随着5G商用大规模落地,以及智能手机硬件性能越来越强、AIoT设备的快速普及,基于云-边缘-端算法和算力结构的...

博文视点Bv
20分钟前
2
0
vim 分屏 操作

$vim -On file file2 #大写O垂直分屏打开文件 $vim -on file file2 #小写水平打开 # n 表示分屏数,直接n等于文件个数 如果n小于文件,按顺序打开前面的n个,如果大于,打开空编辑页面 分屏快...

突突突酱
23分钟前
2
0
MySQL/Mariadb设置中文字符集(linux)

编辑/etc/my.cnf,添加以下设置 [mysql]default-character-set=utf8[mysqld]character_set_server=utf8[mysqld.safe]default-character-set=utf8[client]default-chara...

编程老陆
25分钟前
3
0
关于linux常用的挂载命令

挂载:就把一块磁盘(可以是光盘,U盘)绑定到一个空目录下面 一般情况下会挂载到mnt目录下面 挂载光盘(把光盘挂载到/mnt/cdrom这个目录中) mount -t iso9660 /dev/cdrom /mnt/cdrom 退出当前目录...

chenhongjiang
26分钟前
3
0
如何分享brain内容外部共享?几个需要知道的TheBrain问答

TheBrain(点击下载)是一款与众不同的思维导图软件,其所有信息通过一个又一个的节点进行联系,最终形成一个杂而不乱的网状结构。从头开始设计,让您捕获您的想法和信息在一个网络的联想,匹...

mnrssj
27分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部