Asynchronní dotazy v CURL

Školení, která pořádám

Extenze CURL nabízí podporu asynchronních požadavků. A podobně jako MySQLi neposkytuje zrovna přívětivé API. Vytvořil jsem proto knihovnu, která pokládání vícenásobných požadavků usnadní:

<?php
$http = new CurlAsync;

// položení požadavků
$http->test1("http://www.example.com/");
$http->test2("http://www.example.org/");

// získání odpovědí
print_r($http->test1());
print_r($http->test2());
?>

Knihovna je k dispozici na GitHubu.

Motivace pro asynchronní získávání dat je stejná jako u databáze: výkonnost. Stažení externích URL je obvykle časově náročné, takže hlavně když jich potřebujeme získat víc, vyplatí se to dělat na pozadí. Pokud očekáváme odpověď rychle, lze nastavit $http->timeout = .1.

Jakub Vrána, Řešení problému, 11.10.2010, diskuse: 12 (nové: 0)

Diskuse

optik:

Pardon, ale koukal jsem na to asi tak minutu, i na to předchozí, možná jsem něco přehlédl, ale tohle mi přijde jako fakt hnus, jquery určitě znáš když ho školíš, tak proč ne stejně jednoduše, např.

<?php
$async
= new CurlAsync;
$async->get("http://www.example.com/", function(){});
?>

místo té lambdy může být i 5.2 callback. Takhle to dělá jquery, node.js ... ta lambda z toho udělá teprve to pravé async. Odpadne také brzdící velehnus __call().

ikona Jakub Vrána OpenID:

Současné API byl jen takový pokus. Mám v plánu ho předělat, aby šel přidat interface. Ale callback předávat nebudu, způsob použití tomu neodpovídá. Na vrácená data potřebuješ počkat třeba v šabloně a použít je v určitém kontextu.

No a brát si jako protipříklad zrovna jQuery není úplně nejšťastnější vzhledem k existenci metod jako click(callback), které naváže událost, VS click(), které ji spustí. To je přesně stejná myšlenka.

Používejte diakritiku. Vstup se chápe jako čistý text, ale URL budou převedeny na odkazy a PHP kód uzavřený do <?php ?> bude zvýrazněn. Pokud máte dotaz, který nesouvisí s článkem, zkuste raději diskusi o PHP, zde se odpovědi pravděpodobně nedočkáte.

Jméno: URL: Reakce na: Jakub Vrána

alternate:

Pardon, ale celé PHP s javascriptem je pomalej velehnus:), doufám že se tento trend brzo změní, nerad bych se dožil doby, kde se video v prohlížeči bude renderovat sw javascriptovým kodekem:)

optik:

V pohodě, s php souhlas, s javascriptem ale ne, js vm udělaly za posledních pár let v optimalizaci proti PHP veleskok (abych zůstal u toho velesloví). Dokonce JITují už skoro všechny. Když se nepoužívá eval a ostatní brzdy, javascript bych řekl už na tom bude co se týče optimalizace mnohem lépe než php. A mě představa, že za pár let se bude psát většina aplikací v JS jak na serveru, tak na klientu vůbec nevadí.

ikona Jakub Vrána OpenID:

No tak ono i PHP udělalo veleskok dopředu, i když ne zrovna v oficiální větvi: http://php.vrana.cz/hiphop.php.

optik:

Ne, to není skok dopředu, ale stranou a to je pro majoritu uživatelů php k ničemu u JS engines je situace naprosto odlišná, tam ty vylepšení zasahují v postatě všechny.

kolator:

Když je CURL API nepřívětivé, proč nepoužít přítulnější nadstavbu, kterou ostatně PHP nabízí už dávno? Paralelní dotazy se tam dají poolovat snadno: http://cz.php.net/manual/en/class.httprequestpool.php

optik:

Jojo, škoda že Http PECL extenze u dávno není v core, myslím, že by mohla ušetřit spoustě frameworkům práci.

ikona Jakub Vrána OpenID:

Díky za tip, o tom jsem nevěděl.

starenka:

Jen tak zběžně jsem to prolít' na telefonu, kdyžtak mě po(p)opravte. Chapu to správně, že nejde přidávat vlastní "setopts"?

ikona Jakub Vrána OpenID:

Přesně tak, chtěl jsem co nejjednodušší API. Alternativou by bylo předávat výsledek curl_init($url).

Martin:

Z nějakého důvodu mi nic z výše uvedeného nefungovalo (IIS 7 ?). Nakonec se mi ale podařilo najít funkci, která to zvládá bez problémů. Zavolá stránku a nečeká na výsledek. Pokud na začátek volané stránky dáte     ignore_user_abort(true);, tak se vykoná.

<?php
   
// open a page and don't wait for the result
function curlPostAsync($url, $post_string = "")
{
    $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);
}
?>
avatar © 2005-2019 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.