之前我发现,php未执行完所有代码前(或输出缓冲区满了之前),都不会输出echo语句的内容。如果说想让php代码每隔一段时间就输出一段内容,必然要使用到sleep函数,然而sleep是阻塞函数,php代码要执行完所有sleep后才会一次性把所有echo的内容全输出。
还有一种情况是:echo的内容太多了,达到了缓冲区大小的极限,而php还没执行完,此时也会先输出内容。
php缓冲区的大小一般是1MB,网上有教程查看缓冲区大小。
网上有办法说是输出内容后,再输出一些空内容,使缓冲区大小达到极限,输出内容。我觉得太不靠谱了,输出那么多内容毫无益处,而且不同的php端的缓冲区大小可能不同,这样写出来的代码移植性不高。
后来就是看到输出缓冲区内容的一个函数,flush();
于是我就使用echo 语句输出内容,flush语句把缓冲区内容输出,sleep语句延时,再用js语句清屏再echo再flush,就是下面的代码:
<?php
echo "hello<br/>aa";
// 在php未执行完时就先输出内容,使用flush函数
flush();
sleep(3);
// js清屏
echo "<script>document.body.innerHTML = '';</script>";
echo "yes";
?>
按此原理实现动态改变网页内容。
上述代码之前是可以正常运行的,昨天突然不行了,网上一查要在flush()前加上ob_flush()才行,有人说这样之后无论在什么地方都能输出了。
然而凡事有例外,我这就不行。
可能是我的php版本太老了(五点几的版本)?
但是我也懒得下新的。
那咋整啊。磨了半天,突然这段代码又成功输出内容了,有时可以有时不行。
这也太不稳定了吧,这样不行的。
我的需求大概是这样的:
<?php
while(true)
{
echo "a";
ob_flush();
flush();
sleep(1);
}
?>
上面这段代码预期的执行效果是每隔一秒输出一个a,然而,ob_flush和flush都没有输出内容。
而且由于死循环的存在,php执行超过60s,服务器自动报错,停止执行。
后来我还找到了一个函数
set_time_limit(0);
这个语句可以取消php运行时间的限制,但是仍然无法解决输出不了内容的问题。
仔细想想,我是要隔一段时间执行一段php代码,但是在之前的方案中我是用了sleep语句和flush语句来实现的,但是只要能达到目的,不一定要用flush语句啊!
而且原来的代码还有一个弊端:php代码未执行完之前,就算flush输出了内容,浏览器的标签页上面还是会显示一直在加载,很不好看。
我一拍脑袋啊,马上就给出了解决方案(其实第二天才实现):使用js做定时器,网页可以正常运行,标签页不会保持加载状态,
js的定时器到时间就自动唤醒php代码,php代码不就可以定时执行了嘛!
哇,这个办法不错。
网上一查,js的定时器是setInterval和setTimeout,这两个有区别。
前者是一个保持运作的定时器,时间一到就执行一次语句,如此往复。后者只响应一次。
引用W3C的一句话:
setInterval
函数的用法与setTimeout
完全一致,区别仅仅在于setInterval
指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。
那么我的需求当然得用setInterval来实现喽。
setInterval用法(来自菜鸟教程 https://www.runoob.com/w3cnote/js-timer.html ):
setInterval(code,millisec,lang)
参数 | 描述 |
---|
code | 必需。要调用的函数或要执行的代码串。 |
millisec | 必须。周期性执行或调用 code 之间的时间间隔,以毫秒计。 |
lang | 可选。 JScript | VBScript | JavaScript |
也就是说:
<script>
setInterval("js代码", 定时器时长);
</script>
接下来,有了定时器,如何用js唤醒php代码?
可以用iframe嘛。
设置一个iframe在网页中,给它一个id。
定时器中的js代码设置为重新加载这个iframe,也就是下面这样:
<script>
setInterval("document.getElementById('iframe标签的id').contentWindow.location.reload(true)",定时器长度);
</script>
iframe的src设置为一个php页面,这样下来,每隔一段时间,js定时器就会刷新某个指定的php页面,可以让这个php页面执行一些代码,然后通过session来传递一些值。
如果这个后台php不需要显示在前端,可以把iframe的width,height,frameborder什么的都设置为0,这样就显示不出来了。
差不多就是这样了,讲的这么清楚,该不会有人不知道具体怎么写吧?
js代码都给出来了,自己把iframe补全吧。。。
还有一点,如果说要使php的页面内容定时刷新或者在某条件下刷新,但是不想要整个页面都刷新,只想要某个地方刷新,这一点用js很容易实现,但是如果要用php就有点难受。
可以这样:把要刷新的页面内容写到另一个php页面里,然后在主页面中用iframe显示这个php页面,两个php页面可以用session相互交换数据,而且iframe的属性可以自己调。之后在主页面使用js定时器刷新iframe页面,或者获捕到用户的某操作后用js刷新页面,实现部分内容的刷新。
差不多就是这样了。