0

我正在尝试了解 PHP 回调。我正在使用来自phpriot.com的示例。

---------------this code-----------------------------
 // this function simulates downloading data from a site
    function downloadFromSites($sites, $callback = null)
    {
        $ret = array();

        foreach ($sites as $site) {
            sleep(2);

            $data = 'downloaded data here';

            // check if the callback is valid
            if (is_callable($callback)) {
                // callback is valid - call it with given arguments
                call_user_func($callback, $site, $data);
            }

            // write the data for this site to return array
            $ret[] = array(
                'site' => $site,
                'data' => $data
            );
        }

        return $ret;
    }

    // define a fictional class used for the callback
    class MyClass
    {
        // this is the callback method
        public static function downloadComplete($site, $data)
        {
            echo sprintf("Finished downloading from %s\n", $site);
        }
    }

    // imaginary list of sites to download from
    $sites = array(
        'http://www.example1.com',
        'http://www.example2.com'
        // more sites...
    );

    // start downloading and store the return data
    downloadFromSites($sites, array('MyClass', 'downloadComplete'));

    // we don't need to loop over the return data
    // now since the callback handles that instead

当您运行此代码时,您将看到“完成下载”消息显示为每个站点都已完成,而不是最后全部。


因此,当我在控制台中运行此代码时,它工作正常:每 2 秒出现一个新行,但在浏览器窗口中我必须等到代码完成执行,然后才能看到结果。

所以问题是,为什么它在控制台中工作,而不是在浏览器窗口中工作?

4

2 回答 2

2

这可能是因为输出缓冲。

输出缓冲是 PHP 中的一种机制,它将输出保存在内存中,直到稍后调用flush缓冲区(当脚本关闭时也会自动发生)。

输出缓冲允许您在脚本内打印内容,并在打印内容后提供对 HTTP 标头的更改。通常,一旦您打印内容并将其发送给 apache(后者又将其发送回客户端),您就不能再修改 HTTP 标头了。通过输出缓冲,PHP 会将此输出存储在内存中,并且在您告诉它之前不会将其交给 apache。

您应该能够通过以下四种方式之一使其工作:

  • ob_end_clean在 PHP 脚本的最顶部禁用输出缓冲
  • output_buffering在 php.ini 中禁用
  • 在 php.ini 中启用implicit_flush(不推荐,因为它output_buffering毫无意义
  • ob_flush在您的print/echo陈述之后致电

注意:输出缓冲还有其他非常合法的用途,例如模板 - 但这在这里并不重要。

话虽如此

这不一定适用于所有人。默认情况下,某些浏览器和其他配置的浏览器在连接关闭并收到所有 HTML 内容之前不会开始加载页面。如果您希望它现在可以在大多数浏览器上工作 - 您最好将 AJAX 回调回您的服务器。

编辑:要判断是否output_buffering打开,一个简单的调用print ob_get_level()就会告诉你。如果打印出的数字 > 0,output_buffering那就是罪魁祸首。

于 2013-02-05T13:30:44.323 回答
0

All scripts ran in console come up in real time. This is why it works in the console and not in browser. You have a few options-flush often enough(not a really good solution as most browsers won't be happy about this), use ob_start and on from there or use ajax which is your safest bet I think.

于 2013-02-05T13:37:11.630 回答