Advertisement
Guest User

Untitled

a guest
Oct 3rd, 2016
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 3.48 KB | None | 0 0
  1. <?php declare(strict_types = 1);
  2.  
  3. $database = new Database();
  4.  
  5. // This is know as "continuation passing style". Each asynchronous function call accepts a callback which is
  6. // invoked with the results of the operation.
  7. // This reads in the order in which things happen, but clearly it's less than ideal because our indentation
  8. // level grows with each async operation - and all we did here is fetch some database results.
  9. // Anyone who has worked with Javascript will be familair
  10. $server = new HttpServer(function(Request $request, Response $response) use($database) {
  11.     if ($request->getPath() !== '/foo/ids') {
  12.         $response->setResponseCode(404);
  13.         $response->send();
  14.         return;
  15.     }
  16.  
  17.     // <focus on this section>
  18.     $database->query("SELECT id FROM foo", function(ResultSet $resultSet) use($response) {
  19.         $ids = [];
  20.  
  21.         $resultSet->forEach(function(Result $result) use(&$ids, $response) {
  22.             $ids[] = $result->getColumn('id');
  23.  
  24.             if ($result->isLast()) {
  25.                 $response->send(json_encode($ids));
  26.             }
  27.         });
  28.     });
  29.     // </focus on this section>
  30. });
  31.  
  32. $server->start();
  33.  
  34. // Alternatively we can get rid of the indentation level by defining each step as a function. Let's group those
  35. // definitions together in a class.
  36. // We'll assume that routing is still dealt with at the entry point, and the job of this class is just to build a
  37. // response to the /foo/ids endpoint.
  38. class FooIdsRequestHandler
  39. {
  40.     private $database;
  41.     private $request;
  42.     private $response;
  43.  
  44.     private $ids = [];
  45.  
  46.     function __construct(Database $database, Request $request, Response $response)
  47.     {
  48.         $this->database = $database;
  49.         $this->request = $request;
  50.         $this->response = $response;
  51.     }
  52.  
  53.     function handle()
  54.     {
  55.         $this->database->query("SELECT id FROM foo", [$this, 'onDbResultSet']);
  56.     }
  57.  
  58.     function onDbResultSet(ResultSet $resultSet)
  59.     {
  60.         $resultSet->forEach([$this, 'onDbResult']);
  61.     }
  62.  
  63.     function onDbResult(Result $result)
  64.     {
  65.         $this->ids[] = $result->getColumn('id');
  66.  
  67.         if ($result->isLast()) {
  68.             $this->response->send(json_encode($this->ids));
  69.         }
  70.     }
  71. }
  72.  
  73. // This is an improvement but it's still not great. We have a 33 line class definition which represents a fairly
  74. // trivial routine - and it doesn't even include any error handling. We also can't easily see the order of execution
  75. // of those methods, there's a very high overhead to understanding the code.
  76.  
  77. // Take a step back for a second an think about what that code would look like if it were synchronous:
  78. $resultSet = $database->query("SELECT id FROM foo");
  79.  
  80. $ids = [];
  81.  
  82. while ($result = $resultSet->fetch()) {
  83.     $ids[] = $result->getColumn('id');
  84. }
  85.  
  86. $response->send(json_encode($this->ids));
  87.  
  88. // this code is short and easy to comprehend because it's linear, but it's also synchronous so it has a high cost if we
  89. // want to support a lot of concurrency. Our asynchronous code solves that concurrency problem because it's powered by
  90. // an event loop, but asynchronous code is non-linear and harder to understand.
  91.  
  92. // talk about Generator, look at the parts of it that are not Iterator methods, working towards this code at the end:
  93.  
  94. $resultSet = yield $database->query("SELECT id FROM foo");
  95.  
  96. $ids = [];
  97.  
  98. while ($result = yield $resultSet->fetch()) {
  99.     $ids[] = $result->getColumn('id');
  100. }
  101.  
  102. $response->send(json_encode($this->ids));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement