PHP中是否有一种方法可以使HTTP调用不等待响应?我不关心响应,我只想做一些类似file_get_contents()的事情,但不等待请求完成后再执行其余的代码。这对于在我的应用程序中触发某种“事件”或触发长进程非常有用。
什么好主意吗?
PHP中是否有一种方法可以使HTTP调用不等待响应?我不关心响应,我只想做一些类似file_get_contents()的事情,但不等待请求完成后再执行其余的代码。这对于在我的应用程序中触发某种“事件”或触发长进程非常有用。
什么好主意吗?
当前回答
我之前接受的答案行不通。它仍在等待回应。这虽然工作,采取从我如何使一个异步GET请求在PHP?
function post_without_wait($url, $params)
{
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
$parts=parse_url($url);
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if (isset($post_string)) $out.= $post_string;
fwrite($fp, $out);
fclose($fp);
}
其他回答
如果你控制了你想要异步调用的目标(例如你自己的"longtask.php"),你可以从那端关闭连接,两个脚本将并行运行。它是这样工作的:
quick.php通过cURL打开longtask.php(这里没有魔法) php关闭连接并继续(神奇!) 当连接关闭时,cURL返回quick.php 两项任务同时进行
我试过了,效果不错。但是quick.php不会知道longtask.php正在做什么,除非您在进程之间创建一些通信方式。
在执行其他操作之前,请先在longtask.php中尝试这段代码。它将关闭连接,但仍然继续运行(并抑制任何输出):
while(ob_get_level()) ob_end_clean();
header('Connection: close');
ignore_user_abort();
ob_start();
echo('Connection Closed');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
代码复制自PHP手册的用户贡献注释,并进行了一些改进。
/**
* Asynchronously execute/include a PHP file. Does not record the output of the file anywhere.
*
* @param string $filename file to execute, relative to calling script
* @param string $options (optional) arguments to pass to file via the command line
*/
function asyncInclude($filename, $options = '') {
exec("/path/to/php -f {$filename} {$options} >> /dev/null &");
}
Symfony HttpClient是异步的https://symfony.com/doc/current/components/http_client.html。
例如,你可以
use Symfony\Component\HttpClient\HttpClient;
$client = HttpClient::create();
$response1 = $client->request('GET', 'https://website1');
$response2 = $client->request('GET', 'https://website1');
$response3 = $client->request('GET', 'https://website1');
//these 3 calls with return immediately
//but the requests will fire to the website1 webserver
$response1->getContent(); //this will block until content is fetched
$response2->getContent(); //same
$response3->getContent(); //same
你可以在PHP中使用非阻塞套接字和pecl扩展之一:
http://php.net/event http://php.net/libevent http://php.net/ev https://github.com/m4rw3r/php-libev
您可以使用库,它为您的代码和pecl扩展之间提供了一个抽象层:https://github.com/reactphp/event-loop
您还可以使用基于前面库的异步http-client: https://github.com/reactphp/http-client
查看ReactPHP的其他库:http://reactphp.org
使用异步模型时要小心。 我推荐在youtube上看这个视频:http://www.youtube.com/watch?v=MWNcItWuKpI
我之前接受的答案行不通。它仍在等待回应。这虽然工作,采取从我如何使一个异步GET请求在PHP?
function post_without_wait($url, $params)
{
foreach ($params as $key => &$val) {
if (is_array($val)) $val = implode(',', $val);
$post_params[] = $key.'='.urlencode($val);
}
$post_string = implode('&', $post_params);
$parts=parse_url($url);
$fp = fsockopen($parts['host'],
isset($parts['port'])?$parts['port']:80,
$errno, $errstr, 30);
$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".strlen($post_string)."\r\n";
$out.= "Connection: Close\r\n\r\n";
if (isset($post_string)) $out.= $post_string;
fwrite($fp, $out);
fclose($fp);
}