ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
coroutine.php
Go to the documentation of this file.
1<?php
2
3namespace Sabre\Event;
4
5use Generator;
6use Exception;
7
47function 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}
An exception for terminatinating execution or to throw for unit testing.
An implementation of the Promise pattern.
Definition: Promise.php:23
const PENDING
The asynchronous operation is pending.
Definition: Promise.php:28
error($a_errmsg)
set error message @access public
coroutine(callable $gen)
Turn asynchronous promise-based code into something that looks synchronous again, through the use of ...
Definition: coroutine.php:47
$promise
This example shows demonstrates the Promise api.
Definition: promise.php:16
$type