【问题标题】:Call output of a PHP randomizer via AJAX通过 AJAX 调用 PHP 随机器的输出
【发布时间】:2016-04-15 14:03:58
【问题描述】:

当前设置: 在同一个 PHP 文档中,我有一个 PHP randomizer 函数和调用该函数的 HTML——一个单独的 txt 文档,其中包含由 php 函数调用的字符串:

功能

<?php
function rand_line($fileName, $maxLineLength = 4096) {
  $handle = @fopen($fileName, "strings.txt");
  if ($handle) {
    $random_line = null;
    $line = null;
    $count = 0;
    while (($line = fgets($handle, $maxLineLength)) !== false) {
      $count++;
      if(rand() % $count == 0) {
        $random_line = $line;
      }
    }
    if (!feof($handle)) {
      echo "Error: unexpected fgets() fail\n";
      fclose($handle);
      return null;
    } else {
      fclose($handle);
    }
    return $random_line;
  }
}
?>

我在 HTML 中调用函数:

<?php echo rand_line("strings.txt");?>
<input type="button" value="Another String" onClick="window.location.reload()">

当多个用户访问页面并按下按钮以获得新状态时,这往往会很慢。

我想要达到的目标:

提高性能并使整个事情不那么繁重:也许随机化器过于复杂,例如我可以使用 AJAX 调用,但如果可能的话,将字符串列表保留在 strings.txt 文件中并与 PHP 脚本分开和 HTML。

对不起,如果我不知道我在说什么……我不是一个熟练的程序员。只是一个偶尔把东西拼凑在一起的人:)

【问题讨论】:

  • 您是否可以接受将函数和 HTML 代码分开的答案?
  • strings.txt 一直在变化吗?在那,它是一个永远不会改变的 static 文件吗?或者文件是否不断更新新的字符串?文件中有多少行/*字符串*?
  • 请参阅this answer 以获得从文件中获取随机行的更有效的示例,假设您的文件不是非常大(怀疑您会在用例中遇到内存问题)。您这样做的算法确实相当迂回,进行了不必要的迭代(至少可以在找到某些东西时停止),并且每次迭代都进行不必要的工作(每次新的随机数,检查是否可与行号整除......)跨度>
  • @PatrickGregorio 是的,当然:)
  • @Marcus 它可能会改变,最终可以添加新的字符串。目前该文件有大约 15 个字符串,但我认为它永远不会达到 100。

标签: javascript php jquery html ajax


【解决方案1】:

你真的不想想使用window.location.reload(); 太糟糕了...您确实不想刷新页面...

location.reload() 发送一个全新页面(整个 HTML)的 http 请求,然后不仅您的浏览器需要再次渲染整个 HTML,您还必须通过网络传输更多重复的数据,从 A 点到B点。

您应该只为您需要的数据发送 HTTP 请求(您不再需要整个 HTML,您在第一次访问页面时加载了它)。

相反,使用 XMLHttpRequest javascript 库 (AJAX) 仅请求部分数据(在您的情况下 => 随机行字符串)

HTML:

<!DOCTYPE html>
<html>
<head lang="en">
    <script type="text/javascript">
        function loadDoc(url, cfunc) {
            var xhttp = new XMLHttpRequest();
            xhttp.onreadystatechange = function () {
                if (xhttp.readyState == 4 && xhttp.status == 200) {
                    cfunc(xhttp);
                }
            };
            xhttp.open("GET", url, true)
            xhttp.send();
        }


        function randomLine(xhttp) {
            alert(xhttp.responseText);
        }
    </script>

</head>
<body>

<input type="button" value="Get random line" onClick="loadDoc('http://localhost:8080/myScript.php', randomLine)">

</body>
</html>

PHP:

myScript.php

<?php 
function rand_line($fileName, $maxLineLength = 4096) 
{ 
   ... 
}
echo rand_line("strings.txt");        
?>

【讨论】:

  • @Marcus 我看不出我为什么要重新加载整个页面?能给点吗?这样一来,即使所有内容都被缓存了,并且网络上没有额外的数据,浏览器仍然需要渲染 HTML 和 onload-javascript,如果标签很多,页面肯定会明显变慢。跨度>
  • 在完全没有必要的情况下,为什么还要花费额外的资源。你永远不会知道你的客户有多么好的硬件。如果他有 10 年的电脑,在一些过时的浏览器中打开怎么办……对他来说可能是 2 秒,而不是 0.5 秒。是的,在 string.txt 文件中可能有 100k 行,但我只是假设它是正常大小的文件。肯定会提高性能的一项升级是使用 ajax...所以...
  • @Marcus 另一个通知是用户不喜欢等待页面响应。他们讨厌它。通过使用 AJAX,我们异步请求数据,而用户仍然可以使用页面的其他部分。
  • 另一个例子可能是网络问题,加载页面需要 4 秒。结果将是:用户在空白页面中盯着 4 秒。
  • 我不确定你是否理解,当然它也需要 ajax 调用 4 秒,但由于它是异步的,用户可能不会注意到它,并继续使用不'不需要来自服务器的数据。
【解决方案2】:

*编辑#2*

功能齐全的脚本。通过 PHP 获取初始 字符串,并将其存储在数组中以供以后的 JavaScript 使用。最大限度地减少调用次数。

PHP 从文件中获取字符串;生成一个默认(随机)字符串,以及一个字符串数组供以后与按钮一起使用。

/**
 * @input array $file
 * @return array (mixed) [0] => string, [1] => array
 */
$randomStringFromFile = function($file) {
    if (!$file) return false;

    /**
     * @return Removes carriage returns from the file
     *         and wraps $val with single-quotes so as
     *         to not break JavaScript
     */
    $add_quotes = function(&$val) {
        return str_replace("\n", "", "'$val'");
    };
    return [$file[rand(0, count($file)-1)], array_map($add_quotes, $file)];
};
$randomString = $randomStringFromFile( @file('strings.txt') ) ?: false;

JavaScript

<div id="string_container"><?php echo $randomString[0]; // defaults random string to page ?></div><br>
<button onclick="getString();">Another String</button>
<script>
var getString = function() {
    var arr = [<?php echo implode(',', $randomString[1]); ?>],
        setString = document.getElementById('string_container').innerHTML = arr[Math.floor(Math.random() * arr.length)];
};
</script>

将以上内容放在您的页面中,您应该一切顺利。

编辑(原始)

我们可以使用以下(最快方法)完全从等式中删除 PHP:

<div id="string_container"></div><br>
<button onclick="getString();">Another String</button>
<script>
var getString = function() {
    var request = new XMLHttpRequest(),
        file = 'strings.txt';

    request.open('GET', file);
    request.onload = function() {
        if (request.status === 200) {
            var arr = request.responseText.split("\n"), /** assuming line breaks in file are standard carriage returns (Unix); "\r" if Windows */
                setString = document.getElementById('string_container').innerHTML = arr[Math.floor(Math.random() * arr.length-1)];
        }
    };
    request.send();
};
</script>

带 PHP 的原创

我们可以进一步简化 PHP,从等式中完全删除循环。

$randomStringFromFile = function($file) {
    if (!$file) return false;
    return $file[rand(0, count($file)-1)];
};
echo $randomStringFromFile( @file('strings.txt') ) ?: 'No worky!';

使用file() 将返回数组中的内容,因此您可以简单地随机选择一个键并返回值。

注意平均而言,$file[rand(0, count($file)-1)] 在随机选择密钥时优于 array_rand()(例如 $file[array_rand($file)];)。以微不足道的数量,你有没有.. ~0.0002s~0.0005s,分别。

【讨论】:

    【解决方案3】:

    你可以简化你的代码

    function rand_line($fileName, $maxLineLength = 4096) {
        $f = file($fileName);
        $length = $maxLineLength + 1;
    
        do {
            $line = $f[array_rand($f)];
            $length = strlen($line);
        } while ($length > $maxLineLength);
    
        return $line;
    }
    

    【讨论】:

    • do {} while (0);,真的
    猜你喜欢
    • 2016-08-09
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多