ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
coroutine.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Sabre\Event;
4 
5 use Generator;
6 use Exception;
7 
47 function coroutine(callable $gen) {
48 
49  $generator = $gen();
50  if (!$generator instanceof Generator) {
51  throw new \InvalidArgumentException('You must pass a generator function');
52  }
53 
54  // This is the value we're returning.
55  $promise = new Promise();
56 
57  $lastYieldResult = null;
58 
63  $advanceGenerator = function() use (&$advanceGenerator, $generator, $promise, &$lastYieldResult) {
64 
65  while ($generator->valid()) {
66 
67  $yieldedValue = $generator->current();
68  if ($yieldedValue instanceof Promise) {
69  $yieldedValue->then(
70  function($value) use ($generator, &$advanceGenerator, &$lastYieldResult) {
71  $lastYieldResult = $value;
72  $generator->send($value);
73  $advanceGenerator();
74  },
75  function($reason) use ($generator, $advanceGenerator) {
76  if ($reason instanceof Exception) {
77  $generator->throw($reason);
78  } elseif (is_scalar($reason)) {
79  $generator->throw(new Exception($reason));
80  } else {
81  $type = is_object($reason) ? get_class($reason) : gettype($reason);
82  $generator->throw(new Exception('Promise was rejected with reason of type: ' . $type));
83  }
84  $advanceGenerator();
85  }
86  )->error(function($reason) use ($promise) {
87  // This error handler would be called, if something in the
88  // generator throws an exception, and it's not caught
89  // locally.
90  $promise->reject($reason);
91  });
92  // We need to break out of the loop, because $advanceGenerator
93  // will be called asynchronously when the promise has a result.
94  break;
95  } else {
96  // If the value was not a promise, we'll just let it pass through.
97  $lastYieldResult = $yieldedValue;
98  $generator->send($yieldedValue);
99  }
100 
101  }
102 
103  // If the generator is at the end, and we didn't run into an exception,
104  // we can fullfill the promise with the last thing that was yielded to
105  // us.
106  if (!$generator->valid() && $promise->state === Promise::PENDING) {
107  $promise->fulfill($lastYieldResult);
108  }
109 
110  };
111 
112  try {
113  $advanceGenerator();
114  } catch (Exception $e) {
115  $promise->reject($e);
116  }
117 
118  return $promise;
119 
120 }
$type
An implementation of the Promise pattern.
Definition: Promise.php:23
$promise
This example shows demonstrates the Promise api.
Definition: promise.php:16
coroutine(callable $gen)
Turn asynchronous promise-based code into something that looks synchronous again, through the use of ...
Definition: coroutine.php:47
const PENDING
The asynchronous operation is pending.
Definition: Promise.php:28