PHP的多线程ajax调用

时间:2017-05-25 15:38:14

标签: javascript php ajax multithreading

我正在尝试创建一个网络应用程序,用于确定用户输入的网址中是否有一个或多个电子商务商品缺货。这些网址可以用逗号分隔。目前,我在javascript循环中用逗号分隔后,为每个url调用我的一个PHP脚本调用。以下是代码:

function sendRequest(urls) {

    if (urls.length == 0) {
        return;
    } else {
        var A = urls.split(',');
        for (var i = 0; i < A.length; i++) {
            var xmlhttp = new XMLHttpRequest();
            xmlhttp.onreadystatechange = function () {
                if (this.readyState == 4 && this.status == 200) {
                    var result_set = JSON.parse(this.responseText);
                    if (result_set.flag == 1) {
                        insertRow('stock-table', result_set.url, result_set.title); // It populates a table and insert row in it.
                    }
                }
            };
            xmlhttp.open("GET", "scrapper.php?url=" + A[i], true);
            xmlhttp.send();
        }
    }
}

scrapper.php如下:

<?php
function get_title($data)
{
    $title = preg_match('/<title[^>]*>(.*?)<\/title>/ims', $data, $matches) ? $matches[1] : null;
    return $title;
}
if (!isset($_SESSION['username'])) {
    header("Location: index.php");
}
else if (isset($_GET["url"])) {

    $url = $_GET["url"];
    $title = null;
    $result_set = null;
    $flag = 0;
    $file = fopen($url,"r");
    if (!$file) {
        echo "<p>Unable to open remote file.\n";
        exit;
    }
    while (!feof($file)) {
        $line = fgets($file, 1024);
        if ($title == null){
            $title = get_title($line);
        }
        if (preg_match('/<span[^>]*>Add to Cart/i',
            $line, $matches, PREG_OFFSET_CAPTURE)) {
            break;
        }
        if (preg_match('/Sold Out|Out of Stock/i',
            $line, $matches, PREG_OFFSET_CAPTURE)) {
            $flag = 1;
            break;
        }
    }
    fclose($file);

    $result_set = array("flag" => $flag,
        "url" => $url,
        "title" => $title
    );

    echo json_encode($result_set);

}
?>

现在的问题是:即使对于两个网址,此程序也需要太多时间。虽然,我从file_get_contents()(甚至更慢)移到了这里(ftp解决方案)。我心里很少有困惑:

  1. 考虑我的javascript,是发送一个ajax调用,等待它的响应然后第二个?
  2. 如果第一点不正确,scrapper.php是否能够响应来自循环的第二次调用?因为它忙于handeling第一次ajax调用计算。
  3. 如果第2点为真,我怎么能让它多线程,以便ajax继续发送调用,直到循环结束,scrapper.php为每个调用激活不同的线程,然后在线程完成执行后回复客户端? (一旦线程完成执行,如何制作有限线程池并授予新的ajax响应。因为,我有200个url。因此,制作200个线程绝对不是最佳解决方案)
  4. 如果我将所有网址(大约200个)插入数据库,然后获取所有网址以进行多线程执行,这是一个很好的解决方案。在这种情况下,如何针对单个ajax调用回复多个线程的多个结果?
  5. 请帮助

1 个答案:

答案 0 :(得分:0)

  1. 否。 XMLHttpRequest默认为 async ,这意味着每个具有所述 async 的新请求将并行执行。
  2. 完全取决于你如何运行PHP。在典型的设置中 - 你不太可能不这样做,你的http服务器将等待来自线程池的可用PHP工作线程,或者直接执行PHP二进制文件。无论哪种方式,一次可以执行多个PHP程序。 (想想常规网站的工作原理。您需要一次支持多个用户。)
  3. N / A
  4. 如果我理解正确,您只想在一次Ajax调用中处理所有请求?只需发送请求中所有URL的列表,然后循环服务器端。你目前的做法很好。很可能“慢”性质可归因于您与远程URL的连接。
  5. 其他一些说明:

    • 我会在将URL传递给fopen之前对其进行验证,特别是考虑到用户可以通过简单传递相对路径并开始阅读“私有”文件。
    • 我会切换回file_get_contents。它几乎相当于fopen,但为你做了很多工作。
    • 不确定是否有意,但我会在for循环的内部块中使用较新的const关键字而不是var来获取XMLHttpRequest变量。目前,var被提升到函数范围的顶部,您只需在循环的每次迭代时覆盖它。如果你想为XMLHttpRequest添加更多逻辑,你可能会发现自己容易出现一些无意的行为。