java缓冲流输出_PHP流和输出缓冲介绍
java缓冲流输出
Recently, Rails launched a feature called Streaming. Even though streaming is not a new concept, having it built into the framework to let developers build rapidly responding applications easily is definitely a huge step. As a PHP developer, I was wondering whether we can have something similar in our favorite language? The answer is yes – we can easily have streaming in PHP applications with little effort, but in order to get this right we have to become familiar with some underlying concepts.
最近,Rails推出了一项称为Streaming的功能。 尽管流技术不是一个新概念,但将其内置到框架中以使开发人员轻松构建快速响应的应用程序绝对是一个巨大的步骤。 作为一个PHP开发人员,我想知道我们是否可以用我们喜欢的语言编写类似的东西? 答案是肯定的-我们可以轻松地在PHP应用程序中轻松地进行流传输,但是为了实现这一点,我们必须熟悉一些基本概念。
In this article, we will see what streaming is, what output_buffering is and how to get our desired result under different webservers (Apache, Nginx) and PHP configurations (CGI, mod_php, FastCGI).
在本文中,我们将了解什么是流技术,什么是output_buffering以及如何在不同的Web服务器(Apache,Nginx)和PHP配置(CGI,mod_php,FastCGI)下获得所需的结果。
流和输出缓冲 (Streaming and Output Buffering)
流媒体 (Streaming)
Streaming in web refers to the mechanism of sending responses in chunks rather than sending them at once. In the traditional HTTP request / response cycle, a response is not transferred to the browser until it is fully prepared which makes users wait. This limitation is a remnant of the weak software and hardware of the past, but everything has changed a lot since then. Network systems and browsers are now powerful enough to handle transmission of content in a fast and efficient way. Imagine trying to watch a video and not being able to watch it until it’s fully downloaded into the player’s buffer. With the help of streaming, we can watch videos or listen to our favorite music quite efficiently as content is being loaded instantly while the rest of the data is being downloaded behind the scenes.
Web流是指以块形式发送响应而不是一次发送响应的机制。 在传统的HTTP请求/响应周期中,只有在充分准备好响应之后,响应才会传递给浏览器,这会使用户等待。 这种局限性是过去软件和硬件薄弱的残余,但此后一切都发生了很大变化。 网络系统和浏览器现在功能强大,可以快速有效地处理内容传输。 想象一下试图观看视频,直到将其完全下载到播放器的缓冲区中之后才能观看。 借助流媒体,我们可以高效地观看视频或收听我们喜欢的音乐,因为内容可以立即加载,而其余数据则可以在后台下载。
Streaming seems ideal for giving users the perception that a web-app is loading fast. Streaming of HTTP responses, however, is quite different from streaming of media content. Streaming of HTTP responses simply means sending a response in fixed or variable size chunks to the browser while the webserver is preparing the remainder. For example, you want to display a list of Hollywood movies on a single page. If you prepare the full response first and then send it to browser, the end-user will definitely feel the delay. But if you send 100 movies in one chunk and display them in the browser while you are preparing the HTML for the next 100 movies, the content will feel like it’s loading quite fast.
对于用户来说,流媒体似乎是理想的选择,因为它可以感知Web应用程序正在快速加载。 但是,HTTP响应的流与媒体内容的流非常不同。 HTTP响应流仅意味着在Web服务器准备其余部分时,以固定或可变大小的块将响应发送到浏览器。 例如,您要在单个页面上显示好莱坞电影列表。 如果您先准备完整的响应,然后将其发送到浏览器,则最终用户肯定会感到延迟。 但是,如果您要一整块地发送100部电影,并在为接下来的100部电影准备HTML时在浏览器中显示它们,则内容将感觉加载得非常快。
HTTP responses don’t consist just of renderable items – there are plenty of other things such as response status code, HTTP headers, cookies etc. that are essential parts of a response, but go unnoticed by end-users because they’re never rendered. Without them, our content has no meaning at all. Instead of letting users wait, the bigger sites send the non-renderable information to the browser and once the browser starts receiving it, it starts rotating the loading indicator you’ve almost certainly seen when on slower connections. Stylesheet and JavaScript files remain unchanged for most of the time, so many sites also send them along with non-renderable content chunks, so that the browser starts fetching and executing them while the rest of the response is being prepared. This is quite a powerful technique for creating the illusion of speed. When the content of the body
tag is generated, it is sent to the browser, and that content can be sent in chunks again, further propagating the illusion of speed.
HTTP响应不仅包含可呈现的项目,还有许多其他内容,例如响应状态代码,HTTP标头,Cookie等,它们是响应的重要组成部分,但最终用户不会注意到它们,因为它们从未被呈现。 没有它们,我们的内容将毫无意义。 较大的站点没有让用户等待,而是将不可渲染的信息发送到浏览器,并且一旦浏览器开始接收它,它就会开始旋转连接指示器,这在连接速度较慢时几乎可以肯定地看到。 样式表和JavaScript文件在大多数情况下保持不变,因此许多站点还将它们与不可渲染的内容块一起发送,以便浏览器在准备其余响应时开始获取并执行它们。 这是一种创造速度幻觉的强大技术。 生成body
标记的内容时,它会发送到浏览器,并且该内容可以再次分块发送,从而进一步传播了速度的错觉。
输出缓冲 (Output Buffering)
Output buffering is a mechanism in which instead of sending a response immediately to browser we buffer it somewhere so that we can send it at once when whole content is ready. This is the default way by which PHP sends responses to browsers. We all know that in order to send a response to the browser, we have to use statements like echo
or print
. Each time we are using echo
we are basically telling PHP to send a response to the browser. But since PHP has output buffering enabled by default, that content gets buffered and not sent to the client. Output buffering is configured via output_buffering
in php.ini
and you can see its current configuration value by running phpinfo()
. PHP’s documentation has the following information on output buffering:
输出缓冲是一种机制,该机制不是将响应立即发送到浏览器,而是将其缓冲在某个位置,以便在所有内容准备就绪时可以立即发送响应。 这是PHP将响应发送到浏览器的默认方式。 我们都知道,为了向浏览器发送响应,我们必须使用echo
或print
类的语句。 每次我们使用echo
我们基本上都是在告诉PHP将响应发送给浏览器。 但是由于PHP默认情况下启用了输出缓冲,因此该内容将被缓冲并且不会发送到客户端。 输出缓冲是通过php.ini
output_buffering
配置的,您可以通过运行phpinfo()
来查看其当前配置值。 PHP的文档提供有关输出缓冲的以下信息:
You can enable output buffering for all files by setting this directive to ‘On’. If you wish to limit the size of the buffer to a certain size – you can use a maximum number of bytes instead of ‘On’, as a value for this directive (e.g., output_buffering=4096). As of PHP 4.3.5, this directive is always Off in PHP-CLI.
通过将此指令设置为“ On”,可以为所有文件启用输出缓冲。 如果希望将缓冲区的大小限制为某个大小,则可以使用最大字节数代替“ On”作为该指令的值(例如,output_buffering = 4096)。 从PHP 4.3.5开始,此指令在PHP-CLI中始终为Off。
According to the above information, we can easily see that the default size of the PHP buffer under most configurations is 4096 bytes (4KB) which means PHP buffers can hold data up to 4KB. Once this limit is exceeded or PHP code execution is finished, buffered content is automatically sent to whatever back end PHP is being used (CGI, mod_php, FastCGI). Output buffering is always Off
in PHP-CLI. We will see what this means soon.
根据以上信息,我们可以很容易地看到,大多数配置下PHP缓冲区的默认大小为4096字节(4KB),这意味着PHP缓冲区最多可以容纳4KB的数据。 一旦超过此限制或PHP代码执行完成,缓冲的内容就会自动发送到正在使用的任何后端PHP(CGI,mod_php,FastCGI)。 在PHP-CLI中,输出缓冲always Off
。 我们将很快看到这意味着什么。
It is also worth noting that even webservers may have buffering enabled, which means data fetched from the PHP back end can be buffered by webservers and might override PHP’s settings. Now that we have a pretty solid understanding of streaming and output buffering, let’s take a look at a quick example.
还值得注意的是,甚至网络服务器都可能启用了缓冲,这意味着从PHP后端获取的数据可以由网络服务器缓冲,并且可能会覆盖PHP的设置。 既然我们对流和输出缓冲有了相当深入的了解,那么让我们看一个简单的例子。
一个简单的例子 (A simple example)
Create a file output.php
in your webserver’s root directory so that it is accessible from the browser, e.g. http://localhost/output.php
. Place the following code in output.php
.
在Web服务器的根目录中创建一个文件output.php
,以便可以从浏览器访问它,例如http://localhost/output.php
。 将以下代码放在output.php
。
<?php
echo "Hello ";
sleep(5);
echo "World!";
?>
Go ahead and access this file in your browser. You will not see any content until five seconds have passed, after which the whole “Hello World!” phrase appears. This is because of output buffering. Instead of sending the response to the browser when the first echo
is executed, its contents are buffered. Since buffered content is sent to the browser if either the buffers get full or code execution ends, and since Hello World!
is not enough to occupy more than 4KB of buffer size, the content is sent when code execution ends.
继续并在浏览器中访问此文件。 五秒钟后您才能看到任何内容,此后整个“ Hello World!” 出现短语。 这是由于输出缓冲。 当执行第一个echo
时,它的内容将被缓冲,而不是将响应发送到浏览器。 因为如果缓冲区已满或代码执行结束,并且因为Hello World!
,缓冲的内容都会发送到浏览器Hello World!
不足以超过4KB的缓冲区大小,则在代码执行结束时发送内容。
Now run the same example but this time from the console (the command line) with the following statement:
现在,使用以下语句从控制台(命令行)运行相同的示例,但这一次:
php /path/to/directory/output.php
As soon as you hit enter, you will see the word Hello
appear, and after five seconds the word World!
will appear, too. This is what “always off in PHP-CLI” meant. Because output buffering is off, the response is sent as soon as each echo
is executed.
按下Enter键后,您将看到Hello
一词,五秒钟后出现World!
也会出现。 这就是“在PHP-CLI中始终关闭”的含义。 由于关闭了输出缓冲,因此在执行每个echo
都会立即发送响应。
Now let’s look at output buffering in a bit more detail.
现在让我们更详细地了解输出缓冲。
例子 (Examples)
In the last example, we have seen that because of output buffering in PHP, we don’t get a response until PHP’s execution has finished. This is not desirable since we want to send some content to the browser while we are preparing other responses. As we know, the default size of the output buffer in PHP is 4KB so if we want to send a response to the client we have to generate a response in chunks and each chunk must be 4KB in size. Let’s see an example:
在上一个示例中,我们已经看到由于PHP中的输出缓冲,直到PHP的执行完成,我们才得到响应。 这是不理想的,因为我们希望在准备其他响应时将一些内容发送到浏览器。 众所周知,PHP中输出缓冲区的默认大小为4KB,因此,如果要向客户端发送响应,则必须以块的形式生成响应,每个块的大小必须为4KB。 让我们来看一个例子:
8KB块示例 (8KB chunk example)
<?php
$multiplier = 1;
$size = 1024 * $multiplier;
for($i = 1; $i <= $size; $i++) {
echo ".";
}
sleep(5);
echo "Hello World";
?>
Save the above code in a file in your webserver’s root directory. If you run this example you will see that your browser’s loading indicator didn’t indicate that data is being received until after five seconds. Now, let’s change $multiplier
from 1
to 8
and refresh. If there are no specific settings configured, you’ll notice the browser telling us it started to receive some data almost immediately. Not having to wait for five seconds to realize the page has started loading is very good for user experience.
将以上代码保存在Web服务器的根目录中的文件中。 如果运行此示例,您将看到浏览器的加载指示器直到五秒钟后才指示正在接收数据。 现在,让我们将$multiplier
从1
更改$multiplier
8
并刷新。 如果未配置任何特定设置,您会注意到浏览器告诉我们它几乎立即开始接收一些数据。 无需等待五秒钟即可意识到页面已开始加载,这对用户体验非常有利。
You might be wondering why we have set $multiplier
from 1
to 8
. The reason behind this is related to the webserver’s buffers. Like we said above, at the first level there is the PHP buffering which we can check via the output_buffering
PHP setting. Then, there might be PHP back end (CGI, mod_php, FastCGI) buffering and at the end there might be the webserver’s buffering. Normally, both Nginx and Apache buffer content up to either 4KB
or 8KB
depending on the operating system being used. Normally, on 64bit operating systems, the limit is 8KB
and on 32bit operating systems it is 4KB
.
您可能想知道为什么我们将$multiplier
从1
设置为8
。 其背后的原因与Web服务器的缓冲区有关。 就像我们上面说的,在第一层有PHP缓冲,我们可以通过output_buffering
PHP设置来检查。 然后,可能会有PHP后端(CGI,mod_php,FastCGI)缓冲,最后可能是Web服务器的缓冲。 通常,Nginx和Apache都最多缓冲4KB
或8KB
内容,具体取决于所使用的操作系统。 通常,在64位操作系统上,限制为8KB
,在32位操作系统上,限制为4KB
。
The flow of the above code is as follows, assuming output_buffering
in PHP is set to 4KB
: in the loop when data up to 4KB
has been stored in the PHP buffer due to the echo
statement, PHP automatically sends this data to it’s back end (CGI, mod_php, FastCGI). mod_php
doesn’t buffer data and sends it straight to Apache. CGI
and FastCGI
normally buffer data upto 4KB
by default (depending on configuration) so when they receive it, their buffers get full too so the data is instantly sent to the webserver. The webserver in turns buffers data too, up to 4KB
or 8KB
depending on the operating system. Since I’m using a 64bit operating system, the buffering limit on my side is 8KB
. The server receives data of 4KB
but its buffer size is 8KB
so this will not result in a buffer overflow and no output is sent to the browser. When another 4KB
is prepared by the PHP loop, the aforementioned procedure is repeated but this time because of the already saved 4KB
in the server’s buffer, the coming 4KB
will result in buffer overflow, causing it to clear and be sent to the browser.
上面代码的流程如下,假设PHP中的output_buffering
设置为4KB
:在循环中,由于echo
语句,在PHP缓冲区中存储了最大4KB
数据时,PHP会自动将此数据发送到其后端( CGI,mod_php,FastCGI)。 mod_php
不会缓冲数据,而是直接将其发送到Apache。 CGI
和FastCGI
通常默认情况下FastCGI
缓冲4KB
数据(取决于配置),因此当它们接收数据时,它们的缓冲区也将满,因此数据会立即发送到Web服务器。 Web服务器8KB
根据不同的操作系统缓冲多达4KB
或8KB
数据。 由于我使用的是64位操作系统,因此我的缓冲限制为8KB
。 服务器接收的数据为4KB
但其缓冲区大小为8KB
因此不会导致缓冲区溢出,也不会将任何输出发送到浏览器。 当通过PHP循环准备另一个4KB
,将重复上述过程,但是这一次是由于服务器缓冲区中已经保存了4KB
,即将到来的4KB
将导致缓冲区溢出,从而导致缓冲区清除并发送到浏览器。
Now go ahead and place following the code after $size = 1024 * $multiplier;
:
现在继续在$size = 1024 * $multiplier;
之后放置代码$size = 1024 * $multiplier;
:
$size -= 1;
Refresh, and you will see that this time the browser is not indicating that it has started getting content until five seconds have elapsed. This is because we are iterating the loop to 8KB - 1
times which will not result in a buffer overflow and no data will be sent to browser until after five seconds. Now place the following code before sleep(5);
:
刷新,您将看到这次浏览器直到经过五秒钟才表明它已经开始获取内容。 这是因为我们将循环迭代到8KB - 1
次,这不会导致缓冲区溢出,并且直到五秒钟之后才会有数据发送到浏览器。 现在将以下代码放在sleep(5);
之前sleep(5);
:
echo ".";
Refresh your browser one more time, and you will see that this time the browser is indicating that it has started receiving content without the five second delay. We are iterating the loop to 8KB - 1
times which means that the first 4096 bytes have been pushed towards the server and buffered. When the loop finishes, PHP’s buffers will have 4095 bytes but echo ".";
after the loop is helping us fill the buffer with 4096 bytes, resulting in sending the buffer content to upper layers and thus to the browser.
再刷新一次浏览器,您将看到这次浏览器指示它已开始接收内容,而没有五秒钟的延迟。 我们将循环迭代到8KB - 1
次,这意味着前4096个字节已被推送到服务器并进行了缓冲。 循环结束后,PHP的缓冲区将有4095字节,但echo ".";
循环帮助我们填充4096个字节的缓冲区后,导致将缓冲区内容发送到上层,进而发送到浏览器。
There is one caveat that you should be aware of. PHP’s output_buffering
setting has two possible values. One is to indicate whether it is On
and the second is it to indicate the maximum size of the buffer. If output_buffering
is set to 1
, then you might not be able to see your content or browser loading indicator rotating until PHP code execution is finished. This is because having output_buffering
on 1
means that we have enabled it but haven’t specified a maximum size, so in this case PHP buffers can hold data up to the number in the memory_limit
setting.
您需要注意一个警告。 PHP的output_buffering
设置有两个可能的值。 一种是指示它是否为On
,第二种是指示缓冲区的最大大小。 如果将output_buffering
设置为1
,那么在PHP代码执行完成之前,您可能看不到内容或浏览器加载指示器的旋转。 这是因为将output_buffering
设置为1
意味着我们已启用它,但未指定最大大小,因此在这种情况下,PHP缓冲区最多可以保存memory_limit
设置中的数字。
ob_flush和冲洗 (ob_flush and flush)
We are now familiar with the concept of output buffering and streaming in PHP, and we also know how to send responses in chunks to the browser. However, you might be wondering whether or not there is a better way of sending content in chunks. It is just not feasible to generate 8KB
chunks just to send data to the client in advance because normal web pages don’t have much content and 8KB
is certainly a decent amount of data to be sent in chunks. It’s also not beneficial to send useless data as that will only increase latency. It turns out that there are some built-in methods that we can use to overcome this problem.
现在,我们熟悉了PHP中的输出缓冲和流传输的概念,并且我们还知道如何将响应块发送到浏览器。 但是,您可能想知道是否有更好的方式来分块发送内容。 仅仅生成8KB
块只是为了提前向客户端发送数据是不可行的,因为普通的网页内容不多,而8KB
的数据肯定会以块的形式发送。 发送无用的数据也无益,因为这只会增加延迟。 事实证明,可以使用一些内置方法来克服此问题。
ob_flush()
and flush
are PHP’s built-in methods which are used to send the data to the upper layers. Buffered data is not sent to the upper layers unless the buffers are full or PHP code execution is finished. To send data even when buffers are not full and PHP code execution is not finished we can use ob_flush
and flush
.
ob_flush()
和flush
是PHP的内置方法,用于将数据发送到上层。 除非缓冲区已满或PHP代码执行完成,否则缓冲的数据不会发送到上层。 即使在缓冲区未满且PHP代码执行未完成时也要发送数据,我们可以使用ob_flush
和flush
。
Now let’s see an example:
现在让我们看一个例子:
<?php
$multiplier = 1;
$size = 1024 * $multiplier;
for($i = 1; $i <= $size; $i++) {
echo ".";
}
sleep(5);
echo "Hello World";
?>
In the example above, place the following lines before sleep(5);
在上面的示例中,将以下几行放在sleep(5);
之前sleep(5);
ob_flush();
flush();
Save the file and access it in the browser. As soon as you ask the browser to fetch the web page, you will see that the browser is indicating that it has started to receive content. That’s exactly what we want, because we don’t have to worry about generating content in 8KB
chunks and we can easily stream content to the browser without having to wait for the whole content to be generated. You can try different multipliers to get a more solid grip on these concepts.
保存文件并在浏览器中访问它。 要求浏览器获取网页后,您将立即看到浏览器指示它已开始接收内容。 这正是我们想要的,因为我们不必担心会以8KB
块生成内容,并且我们可以轻松地将内容流式传输到浏览器,而不必等待整个内容生成。 您可以尝试使用不同的乘数,以更扎实地掌握这些概念。
There are, however, some caveats that you should be aware of. The above code will work fine in Apache with mod_php
. It will even work without the for
loop. As soon as ob_flush()
and flush()
are executed, the browser will start indicating that some content is coming. However, ob_flush()
and flush()
might not work with Nginx out of the box because of the way Nginx processes requests. In order for ob_flush
and flush
to work seamlessly in Nginx you can use following configuration:
但是,您需要注意一些注意事项。 上面的代码通过mod_php
在Apache中可以正常工作。 它甚至可以在没有for
循环的情况下工作。 一旦执行了ob_flush()
和flush()
,浏览器就会开始指示某些内容即将到来。 但是,由于Nginx处理请求的方式, ob_flush()
和flush()
可能不适用于Nginx。 为了使ob_flush
和flush
在Nginx中无缝运行,可以使用以下配置:
fastcgi_buffer_size 1k;
fastcgi_buffers 128 1k; # up to 1k + 128 * 1k
fastcgi_max_temp_file_size 0;
gzip off;
You can find out more about this in this post.
使用Ajax流式传输 (Streaming with Ajax)
Now that we have seen how to send content in chunks in a standard HTTP request / response cycle, let’s see how to do the same for Ajax requests. Ajax requests are a nice and elegant way of getting data without reloading the full page. We associate a callback with an Ajax request and that callback gets executed once all content is received. This means that we cannot stream content in Ajax requests. Luckily, we have XMLHTTPRequest 2
, which is the next version of the Ajax API and supported in the latest browsers. This new version has a lot of cool features such as cross-origin requests, uploading progress events and support for uploading / downloading binary data. Progress events are used to tell the user how much data we have uploaded, and we can also get downloaded data in chunks. Let’s see an example:
既然我们已经了解了如何在标准的HTTP请求/响应周期中按块发送内容,那么让我们来看看如何对Ajax请求执行相同的操作。 Ajax请求是一种无需重新加载整个页面即可获取数据的好方法。 我们将回调与Ajax请求相关联,并且一旦收到所有内容,该回调便会执行。 这意味着我们无法流式传输Ajax请求中的内容。 幸运的是,我们有XMLHTTPRequest 2
,它是Ajax API的下一个版本,并且在最新的浏览器中受支持 。 这个新版本具有许多很酷的功能,例如跨源请求,上载进度事件以及支持上载/下载二进制数据。 进度事件用于告诉用户我们上传了多少数据,我们还可以分块获取下载的数据。 让我们来看一个例子:
Create an HTML file with the following code:
使用以下代码创建一个HTML文件:
<html>
<head>
<title>Ajax Streaming Test</title>
</head>
<body>
<center><a href="#" id="test">Test Ajax Streaming</a></center>
<script type="text/javascript">
document.getElementById('test').onclick = function() {
xhr = new XMLHttpRequest();
xhr.open("GET", "response.php", true);
xhr.onprogress = function(e) {
alert(e.currentTarget.responseText);
}
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
console.log("Complete = " + xhr.responseText);
}
}
xhr.send();
};
</script>
</body>
</html>
Now load this file in browser and click the link. An Ajax request is initiated to fetch data from response.php
and we are listening to the onprogress
event. Whenever a new chunk arrives, we output it in an alert.
现在,将此文件加载到浏览器中,然后单击链接。 启动Ajax请求以从response.php
获取数据,我们正在监听onprogress
事件。 每当有新块到达时,我们都会在警报中输出它。
Now put the following code in response.php
and save it in the same folder, relative to the above HTML file.
现在,将以下代码放入response.php
,并将其保存在相对于上述HTML文件的同一文件夹中。
<?php for ($i = 1; $i <= 10; $i++): ?>
<?php sleep(1); ?>
Count = <?php echo "$i\n"; ?>
<?php ob_flush(); flush(); ?>
<?php endfor; ?>
As you can see, we run a loop ten times, pausing for one second on each run and then echoing some content. This content gets sent to the upper layers with the flushes. Now go ahead and click on Test Ajax Streaming
. If all goes well, you’ll notice Count = 1
getting displayed in an alert. When you dismiss the alert, you’ll see another alert with Count = 1 \n Count = 2
. When you dismiss that one, you’ll see Count = 1 \n Count = 2 \n Count = 3
in another alert, and so on until 10. When the entire Ajax request is successfully completed, you will see the complete output in the console. We have just implemented streaming in Ajax requests and we can easily update our interface accordingly, giving end-users an outstanding experience.
如您所见,我们运行十次循环,每次运行暂停一秒钟,然后回显某些内容。 该内容随同冲洗一起发送到上层。 现在继续并单击Test Ajax Streaming
。 如果一切顺利,您会发现Count = 1
出现在警报中。 解除警报后,您将看到另一个Count = 1 \n Count = 2
警报。 撤消该警报后,您将在另一个警报中看到Count = 1 \n Count = 2 \n Count = 3
,依此类推,直到10。当整个Ajax请求成功完成时,您将在窗口中看到完整的输出。安慰。 我们刚刚在Ajax请求中实现了流传输,并且我们可以轻松地相应地更新我们的界面,从而为最终用户提供出色的体验。
Note: there are some browser incompatibilities. Test the above code in both Chrome and Firefox. Firefox will behave exactly as demonstrated in terms of output, but Chrome will display an empty alert first, and then continue as expected. Keep this edge case in mind when implementing streaming!
注意:浏览器存在一些不兼容性。 在Chrome和Firefox中测试上述代码。 Firefox的行为将完全按照输出显示,但Chrome会先显示一个空警报,然后按预期继续。 实施流媒体时请牢记这种情况!
结论 (Conclusion)
Streaming is an awesome way of sending content to the user in order to simulate speed. But like everything, streaming is not a silver bullet and it has it’s own shortcomings. The following are some situations where streaming is not an ideal solution:
流是一种向用户发送内容以模拟速度的绝佳方法。 但是像其他所有内容一样,流媒体并不是万灵药,它有其自身的缺点。 以下是流式传输不是理想解决方案的一些情况:
-
Handling exceptions: A status code is essential for browsers to determine the success / failure of every request. Since we have sent the status code in advance along with headers, cookies etc. if at some point an exception occurs on the server side, the server will not be able to convey it to browser since the status code is already sent.
处理异常:状态代码对于浏览器确定每个请求的成功/失败至关重要。 由于我们已经预先发送了状态代码以及标头,Cookie等,因此如果在服务器端发生异常,服务器将无法将其传递给浏览器,因为状态代码已经发送出去了。
-
Sending small chunks of data is inefficient as networks prefer a small number of chunks with bigger responses instead of a high number of chunks with smaller responses. In order to send content in chunks, we have to choose the chunk size carefully.
发送少量数据块的效率很低,因为网络更喜欢少量具有较大响应的块,而不是大量具有较小响应的块 。 为了分块发送内容,我们必须仔细选择块大小。
I hope this article helped you grasp the basics of streaming and buffers. Please let us know of other experiments you came up with after reading this, if any, and of course, leave your feedback in the comments below. Would you like to see more examples? More explanations? Let us know!
我希望本文能帮助您掌握流和缓冲区的基础。 阅读本文后,请告知我们您进行的其他实验(如果有),当然,请将您的反馈留在下面的评论中。 您想查看更多示例吗? 更多解释? 让我们知道!
翻译自: https://www.sitepoint.com/php-streaming-output-buffering-explained/
java缓冲流输出