André Roaldseth
Developer at NAV
andrer@dev:~/http-analyzer (master)$ ./http-analyzer analyze github.com
GET: http://github.com
IP: 192.30.252.129
Status Code: 200
Time spent in 1 redirection(s): 302 ms
Response size: 12.3 KB
DNS Lookup: 60.9 ms
Connecting: 188.7 ms
Sending: 0.1 ms
Waiting (TTFB): 637.7 ms
Recieving: 0.6 ms
Total time: 940.3 ms
Actual transfer is 0.6 ms. The rest is waiting on network.
<?php
require 'vendor/autoload.php';
$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket, $loop);
$app = function ($request, $response) {
$response->writeHead(200, array('Content-Type' => 'text/plain'));
$response->end("Hello World\n");
};
$http->on('request', $app);
$socket->listen(1337);
echo "Server running at http://127.0.0.1:1337\n";
$loop->run();
In its simplest definition, a stream is a resource object which exhibits streamable behavior.
That is, it can be read from or written to in a linear fashion, and may be able to fseek() to an arbitrary locations within the stream.- PHP Manual
Emits these events:
Provides these methods:
Emits these events:
Provides these methods:
$loop = React\EventLoop\Factory::create();
$source = new React\Stream\Stream(fopen('omg.txt', 'r'), $loop);
$dest = new React\Stream\Stream(fopen('wtf.txt', 'w'), $loop);
$source->pipe($dest);
$loop->run();
$redis = new Predis\Client();
$loop = React\EventLoop\Factory::create();
$buffer = '';
$dest = new React\Stream\Stream(fopen('local-copy.txt', 'w'), $loop);
$source = new React\Stream\Stream(fopen('http://internet/4GB-file.txt', 'r'), $loop);
$source->on('data', function($data) use (&$buffer, $redis) {
$buffer .= $data;
if (strpos($buffer, PHP_EOL) !== false) {
foreach (explode(PHP_EOL, $buffer) as $line) {
$redis->rpush('queue', $line);
}
$buffer = '';
}
});
$dest->pipe($source);
$loop->run();
A Deferred represents a computation or unit of work that may not have completed yet.
While a Deferred represents the computation itself, a Promise represents the result of that computation.
A Resolver can resolve, reject or trigger progress notifications on behalf of a Deferred without knowing any details about consumers.
<?php
function doAsyncHttpRequest($url) {
$deferred = new React\Promise\Deferred();
// Pass only the Resolver
fetchHttpAsynchronously($deferred->resolver(), $url);
// Return only the Promise, so that the caller cannot
// resolve, reject, or otherwise work with the original Deferred.
return $deferred->promise();
}
$promise = doAsyncHttpRequest('http://api.awesome.com/sauce/21');
$promise->then(function($apiResponse) {
echo 'API responded with ' . $apiResponse;
});
<?php
function doAsyncHttpRequest($resolver, $url) {
// Perform the HTTP request asynchronously and
// resolve the promise using the API response.
$resolver->resolve($response);
}
interface PromiseInterface {
public function then(
callable $fulfilledHandler = null,
callable $errorHandler = null,
callable $progressHandler = null
);
}
interface ResolverInterface { public function resolve(mixed $result = null); public function reject(mixed $reason = null); public function progress(mixed $update = null);
}
$promise = React\Promise\When::all(
array|React\Promise\PromiseInterface $promisesOrValues,
callable $fulfilledHandler = null,
callable $errorHandler = null,
callable $progressHandler = null
);
$promise = React\Promise\When::any(
array|React\Promise\PromiseInterface $promisesOrValues,
callable $fulfilledHandler = null,
callable $errorHandler = null,
callable $progressHandler = null
);
$promise = React\Promise\When::some(
array|React\Promise\PromiseInterface $promisesOrValues,
integer $howMany,
callable $fulfilledHandler = null,
callable $errorHandler = null,
callable $progressHandler = null
);
$promise = React\Promise\When::map(
array|React\Promise\PromiseInterface $promisesOrValues,
callable $mapFunc
);
$promise = React\Promise\When::reduce(
array|React\Promise\PromiseInterface $promisesOrValues,
callable $reduceFunc,
$initialValue = null
);
function multiplyNumbers($a, $b) {
return $a * $b;
}
$vat = 1.24;
$priceA = 100;
$priceAWithVat = multiplyNumbers($price, $vat);
$priceB = 300;
$priceBWithVat = multiplyNumbers($price, $vat);
$addVat = React\Partial\bind('multiplyNumbers', 1.24);
$priceA = 100;
$priceAWithVat = $addVat($price);
$priceB = 100;
$priceBWithVat = $addVat($price);
$url = 'http://www.vg.no';
$promise = performAsyncGet($url);
function responseHandler($url, $response) {
// Your handler wants both the $url and $response
}
$promise->then('responseHandler'); // But.. we have no URL?
$promise->then(function($data) use ($url) {
responseHandler($url, $data);
});
$promise->then(React\Partial\bind('responseHandler', $url));
<?php
require 'vendor/autoload.php';
$loop = React\EventLoop\Factory::create();
$dnsResolverFactory = new React\Dns\Resolver\Factory();
$dnsResolver = $dnsResolverFactory->createCached('8.8.8.8', $loop);
$factory = new React\HttpClient\Factory();
$client = $factory->create($loop, $dnsResolver);
function handleResponse($resolver, $response) {
$body = '';
$response->on('data', function ($data) use (&$body) {
$body .= $data;
});
$response->on('end', function() use (&$body, $resolver) {
$resolver->resolve($body);
});
}
$promises = [];
foreach (['http://www.vg.no', 'http://www.google.com'] as $url) {
$deferred = new React\Promise\Deferred();
$promise = $deferred->promise();
$promise->then(function($data) use ($url) {
// Executed when the $url is loaded and does not know about any other requests.
printf('%s responded with %d bytes' . PHP_EOL, $url, strlen($data));
});
$request = $client->request('GET', $url);
$request->on('response', React\Partial\bind('handleResponse', $deferred->resolver()));
$request->end();
$promises[] = $promise;
}
React\Promise\When::reduce($promises,
function ($value, $data) {
return strlen($data) + $value;
}
)->then(function($data) {
printf('Downloaded %d bytes in total.' . PHP_EOL, $data);
});
$loop->run();
http://www.google.com responded with 258 bytes http://www.vg.no responded with 255766 bytes Downloaded 256024 bytes in total.
By André Roaldseth