用户
 找回密码
 入住 CI 中国社区
搜索
楼主: 方达
收起左侧

[Web] 关于CodeIgniter实现BigPipe的一些讨论

  [复制链接]
发表于 2012-7-4 21:22:46 | 显示全部楼层
方达 发表于 2012-7-4 17:38
我问题解决了....
当知道真相,我眼泪都要留下来了...

首先你的理解是错误的。
ci的load->view('tpl', true) 第二个参数为true,内部实现为ob_start(); $result = ob_get_contents();ob_end_clean();

1、想要实现输出缓冲这种效果,首先必须执行ob_end_clean()来情况缓冲区并关闭。
2、个别浏览器第一个缓冲区数据必须大于一定长度才会输出,一般开头我们会echo str_pad('', 1000);

例如:

<?php
ob_end_clean();
echo str_pad('',1024);
echo 'a';
flush();
for($i = 0; $i<10; $i++)
{
        echo $i.'<br />';
        flush();
        sleep(1);
}

评分

参与人数 1威望 +5 收起 理由
方达 + 5

查看全部评分

 楼主| 发表于 2012-7-4 21:37:23 | 显示全部楼层
本帖最后由 方达 于 2012-7-4 22:29 编辑
太尉天上飞 发表于 2012-7-4 21:22
首先你的理解是错误的。
ci的load->view('tpl', true) 第二个参数为true,内部实现为ob_start(); $result ...

"个别浏览器"是不是指IE呢~~我知道"个别版本IE只有当接受到256字节以后才开始显示页面“(取自PHP Manual -- flush)

另外,我按照我自己的方法,实测过是work的。
虽然不知道为什么,但是,我实际测试得出的结论,确实是
“没有<meta...>标签,不管怎么写也不能有flush的效果,而加了之后有了flush的效果”
我最后就是这样解决的...

具体来说,这个work的解决方案为:
1.在第一个加载的view中,务必包含<meta...>标签
2.
ob_start();
echo $this->load->view('skeleton',array(),TRUE);
ob_flush();
flush();
echo $this->load->view('content',array(),TRUE);
ob_flush();
flush();

这个是work的...
 楼主| 发表于 2012-7-4 21:40:44 | 显示全部楼层
本帖最后由 方达 于 2012-7-4 22:45 编辑
太尉天上飞 发表于 2012-7-4 21:22
首先你的理解是错误的。
ci的load->view('tpl', true) 第二个参数为true,内部实现为ob_start(); $result ...

//你帖子中的代码推翻了我下面帖子的内容,不过下面这贴我不想删了 -- 写在发帖后
我甚至写了这样两个文件来测:

第一个文件test_one.php:
<meta...>
<?php
...
?>

第二个文件test_two.php:
<?php
...
?>

test_one.php实测有flush的效果,test_two.php没有flush的效果,而是阻塞到最后一起返回所有结果的
 楼主| 发表于 2012-7-4 21:42:30 | 显示全部楼层
太尉天上飞 发表于 2012-7-4 21:22
首先你的理解是错误的。
ci的load->view('tpl', true) 第二个参数为true,内部实现为ob_start(); $result ...

没有任何其他不一样的地方,区别仅仅就是view中的一个meta标签...
虽然不知道为什么,但是它的确是work
 楼主| 发表于 2012-7-4 22:40:54 | 显示全部楼层
本帖最后由 方达 于 2012-7-4 22:55 编辑
太尉天上飞 发表于 2012-7-4 21:22
首先你的理解是错误的。
ci的load->view('tpl', true) 第二个参数为true,内部实现为ob_start(); $result ...

但是虽然我是这样来实现的,也不想改了。
你的观点我是赞同的
你提出的方案也是一个work的方案。echo str_pad();提前填充是可行的。

只是因为我实际操作中的方案也是work的,所以去掉'echo str_pad();'
转而在view头上加meta标签,也是可行的。

我能不能这样理解,加meta标签后,修改了浏览器的默认设置么
发表于 2012-7-6 01:20:42 | 显示全部楼层
ci的view输出是有buffer的,所以你的flush是无效的。不过你可以扩展loader类实现你的想法~我支持你~
发表于 2012-7-6 01:28:19 | 显示全部楼层
另,佩服楼主的钻研精神!
 楼主| 发表于 2012-7-6 09:55:18 | 显示全部楼层
本帖最后由 方达 于 2012-7-6 09:59 编辑
Hex 发表于 2012-7-6 01:28
另,佩服楼主的钻研精神!

谢谢Hex的鼓励!

对的,我简单阅读过Load类,的确在load view之后会有buffer。
但我认为执行Output.php中的_display()之后,CI不会对view再做buffer了。

由于之前没有找到原因,所以一度怀疑_display()之后是否CI又做了buffer
事实上的最后找到的原因是和浏览器本身运行的机制有关。

事后问过某位大牛,他给了一个解释。意思是,如果返回浏览器的数据不加<meta>标签,
则浏览器会在读数据的过程中一直猜测这数据代表的是html还是xml还是别的文档类型,
直到最后才输出所有数据,所以给人造成最后一刻一起flush的幻觉。

评分

参与人数 1威望 +5 收起 理由
cdm + 5 感谢反馈

查看全部评分

发表于 2012-7-6 10:19:51 | 显示全部楼层
方达 发表于 2012-7-6 09:55
谢谢Hex的鼓励!

对的,我简单阅读过Load类,的确在load view之后会有buffer。

楼主有没有考虑过增加的<meta标签只是填充了第一次输出数据的长度呢?

另外你的代码:
ob_start();
echo $this->load->view('skeleton',array(),TRUE);
ob_flush();
flush();
echo $this->load->view('content',array(),TRUE);
ob_flush();
flush();
之前没有时间间隔,比如sleep(1),怎么看出缓冲输出的。
 楼主| 发表于 2012-7-6 10:55:54 | 显示全部楼层
本帖最后由 方达 于 2012-7-6 10:59 编辑
太尉天上飞 发表于 2012-7-6 10:19
楼主有没有考虑过增加的load->view('skeleton',array(),TRUE);
ob_flush();
flush();

我认为不是meta标签进行了填充的原因,我得出这个结论原因有二
1.meta标签中,缺少content="text/html;charset=utf-8" 或者是http-equiv="Content-Type"的话,
按我的方法都不work,一定要两个都加才work。
2.这样写也不work:(缺少http-equiv="Content-Type")
HTML复制代码
 
<meta name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" content="text/html;charset=utf-8" >
 
复制代码

这样也不work:(缺少content="text/html;charset=utf-8")
HTML复制代码
 
<meta name = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" http-equiv="Content-Type" >
 
复制代码



测试的时候在两次中间是添加sleep()的,
之后再去掉的。

本版积分规则