1

I have a bunch of remote content providers whose APIs are queried to respond to a user request. Assuming every content provider needs to be queried, how would I issue the API requests asynchronously and collect the results? For now I am just iterating over my collection of content providers and call their API one by one like this:

/**
 * A wrapper method that delegates requests to content providers.
 */
public function __call($name, $args) {

    // do stuff before

    $results = array();
    foreach ($contentProviders as $contentProvider) {
        $callback = array($contentProvider, $name), $args);
        $results[get_class($contentProvider)] = call_user_func_array($callback);
    }

    // do stuff after

    // build final result from individual calls

    return $result;
}

This, however, leaves me waiting until a request is complete before starting the next one. Is there even a way to do this asynchronously in PHP?

Thyrel
  • 195
  • 4
  • 13

1 Answers1

0

Probably if you are using PHP5 this post of Wez Furlong will help you: http://wezfurlong.org/blog/2005/may/guru-multiplexing/

Sample code from the mentioned page:

<?php
$hosts = array("host1.sample.com", "host2.sample.com", "host3.sample.com");
$timeout = 15;
$status = array();
$sockets = array();
/* Initiate connections to all the hosts simultaneously */
foreach ($hosts as $id => $host) {
    $s = stream_socket_client("$host:80", $errno, $errstr, $timeout, 
        STREAM_CLIENT_ASYNC_CONNECT|STREAM_CLIENT_CONNECT);
    if ($s) {
        $sockets[$id] = $s;
        $status[$id] = "in progress";
    } else {
        $status[$id] = "failed, $errno $errstr";
    }
}
/* Now, wait for the results to come back in */
while (count($sockets)) {
    $read = $write = $sockets;
    /* This is the magic function - explained below */
    $n = stream_select($read, $write, $e = null, $timeout);
    if ($n > 0) {
        /* readable sockets either have data for us, or are failed
         * connection attempts */
        foreach ($read as $r) {
            $id = array_search($r, $sockets);
            $data = fread($r, 8192);
            if (strlen($data) == 0) {
                if ($status[$id] == "in progress") {
                    $status[$id] = "failed to connect";
                }
                fclose($r);
                unset($sockets[$id]);
            } else {
                $status[$id] .= $data;
            }
        }
        /* writeable sockets can accept an HTTP request */
        foreach ($write as $w) {
            $id = array_search($w, $sockets);
            fwrite($w, "HEAD / HTTP/1.0\\r\\nHost: "
                . $hosts[$id] .  "\\r\\n\\r\\n");
            $status[$id] = "waiting for response";
        }
    } else {
        /* timed out waiting; assume that all hosts associated
         * with $sockets are faulty */
        foreach ($sockets as $id => $s) {
            $status[$id] = "timed out " . $status[$id];
        }
        break;
    }
}
foreach ($hosts as $id => $host) {
    echo "Host: $host\\n";
    echo "Status: " . $status[$id] . "\\n\\n";
}
?>
artberri
  • 1,327
  • 13
  • 26
  • Unfortunately, I don't call the API directly but let the individual libraries take care of handling the request, so I'm rather looking for some kind of threading. – Thyrel Feb 22 '15 at 22:32
  • 1
    If you are searching for multi-threading in PHP maybe this can help you: http://stackoverflow.com/questions/209774/does-php-have-threading – artberri Feb 22 '15 at 22:38