首页 > 解决方案 > 当你得到它们并继续请求更多时,从 http 请求中回显数据

问题描述

我现在设法获得了一个工作代码,但这不是我想要的,http 调用每个响应都会返回 2 个结果,并且只要有更多结果,它就会继续执行相同的调用,目前这项工作有效,但对于某些结果它可以需要很长时间,因为有超过 100 个结果。有没有办法在你得到结果后立即回应结果并不断呼吁更多结果?

如果代码看起来很糟糕,我从来没有使用过 php。

<?php
$par = $_GET['par1'];
$results = array();
htcall($results, $par);
echo $results;

function htcall(&$results, $par)
{
    $done = false;
    $lid = -1;

    while ($done == false) {
        inner($par, $lid, $done, $results);
    }

    echo 'done.';
}

function inner($par, &$lid, &$done, &$results)
{
    $ch = curl_init();
    $url = 'http url';
    if ($lid == -1) {
        $body = "id=" .  $par;
    } else {
        $body = "id=" .  $par. "&lid=" . $lid;
    }
    $headers = [
        'Host: host',
        'Content-Type: application/x-www-form-urlencoded',
    ];

    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $resp = curl_exec($ch);
    if ($e = curl_error($ch)) {
        echo 'Request Error:' . $e;
        curl_close($ch);
    } else {
        $decoded = json_decode($resp, true);
        foreach ($decoded as $key => $value) {
            if (is_array($value)) {
                foreach ($value as $key1 => $value1) {
                    if ($value1['title'] == 'noMore') {
                        $done = true;
                    } else {
                        $lid = $value1['id'];
                        array_push($results, $value1['title']);
                    }
                }
            }
        }
        curl_close($ch);
    }
}
?php>

标签: phpapihttpasynchronouscurl

解决方案


目前,您仅在一切完成后才回显数据,而不是在完成时。为此,您需要通过分离每个函数所关注的或需要关注的内容来稍微重新构造代码。

例如,您需要一个函数来发出 POST 请求,但它不必了解数据本身的任何信息——它只需要发送请求和接收响应。它甚至不必知道如何处理错误:

/**
 * Send POST requests to given URL with given data. 
 *
 * @return array
 */
function http_post(string $url, string $data): array {

    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);
    $error    = curl_error($ch);

    curl_close ($ch);

    // Just return right away, do not be concerned with anything else
    return $error ? [false, $error] : [true, $response];
}

本着同样的精神,让我们考虑一下查询字符串是如何构建的。这并不多,但从长远来看,它会有所帮助,例如当您的查询变得复杂时。这绝对是它自己的一个问题:

/**
 * Builds a query string based on the given data.
 * 
 * @return String
 */
function build_query_string($id, $lid): string {

    return ($lid == -1) ? "id={$id}" : "id={$id}&lid={$lid}"; 
}

剩下的就是收集您的数据。尽管还有很多空间可以考虑更多因素,但让我们一口气完成 - 最重要的是,根据您的问题,让我们尝试在每次请求后立即提供反馈:

/**
 * Triggers POST requests, collects & evaluates the respective responses.
 * 
 * @return array
 */
function collect_post_data($url, $id, $lid) {

    $stack        = [];
    $query_string = build_query_string($id, $lid);

    while (true) {

        // Get & evalute $response 
        
        list($success, $response) = http_post($url, $query_string);

        if (!$success) {

            return $stack; // Or thrown an error, or...
        }

        // Best move this part to a separate function, too

        $response = json_decode($response, true);

        foreach ($response as $key => $value) {

            // Build a new query string, 
            // set $continue to false if $value1['title'] == 'noMore', ...
        }

        $stack[] = $response;

        // Give some feedback
         
        var_dump($response); // If this is part of a command-line script, var_dump()
                             // happens right away. 

        if (php_sapi_name() != 'cli') { // But if this is part of a website/webapp...

            ob_flush(); //...than we have to flush the output buffer...
            flush();    //...which is a two-step-process, cf. https://www.php.net/manual/en/function.flush.php
        }

        // Mock an exit condition

        if (count($stack) > 10) {

            return $stack;
        }
    }
}

最后,我们可以通过以下方式启动整个过程:

$id  = 1; // Probably data coming in...
$lid = 1; // ...from somewhere else

// Executes a bunch of requests & var_dumps() the results along the way
$results = collect_post_data('https://httpbin.org/post', $id, $lid);

推荐阅读