/** * wait for ANY of the given promises to resolve * * Once the first promise is resolved, this will try to cancel() all * remaining promises and return whatever the first promise resolves to. * * If ALL promises fail to resolve, this will fail and throw an Exception. * * @param array $promises * @param LoopInterface $loop * @return mixed returns whatever the first promise resolves to * @throws Exception if ALL promises are rejected */ function awaitAny(array $promises, LoopInterface $loop) { try { // Promise\any() does not cope with an empty input array, so reject this here if (!$promises) { throw new UnderflowException('Empty input array'); } $ret = await(Promise\any($promises)->then(null, function () { // rejects with an array of rejection reasons => reject with Exception instead throw new Exception('All promises rejected'); }), $loop); } catch (Exception $e) { // if the above throws, then ALL promises are already rejected // (attention: this does not apply once timeout comes into play) throw new UnderflowException('No promise could resolve', 0, $e); } // if we reach this, then ANY of the given promises resolved // => try to cancel all promises (settled ones will be ignored anyway) _cancelAllPromises($promises); return $ret; }
public function create($host, $port) { $all = array(); foreach ($this->managers as $connector) { /* @var $connection Connector */ $all[] = $connector->create($host, $port); } return Promise\any($all)->then(function ($conn) use($all) { // a connection attempt succeeded // => cancel all pending connection attempts foreach ($all as $promise) { if ($promise instanceof CancellablePromiseInterface) { $promise->cancel(); } // if promise resolves despite cancellation, immediately close stream $promise->then(function ($stream) use($conn) { if ($stream !== $conn) { $stream->close(); } }); } return $conn; }); }