Promises::get()   B
last analyzed

Complexity

Conditions 4
Paths 8

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 31
rs 8.5806
c 0
b 0
f 0
cc 4
eloc 18
nc 8
nop 3
1
<?php
2
3
/*
4
 * This file is part of the Cubiche package.
5
 *
6
 * Copyright (c) Cubiche
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Cubiche\Core\Async\Promise;
13
14
use Cubiche\Core\Async\Loop\LoopInterface;
15
16
/**
17
 * Promises class.
18
 *
19
 * @author Karel Osorio Ramírez <[email protected]>
20
 */
21
class Promises
22
{
23
    /**
24
     * @return \Cubiche\Core\Async\Promise\DeferredInterface
25
     */
26
    public static function defer()
27
    {
28
        return new Deferred();
29
    }
30
31
    /**
32
     * @param mixed $value
33
     *
34
     * @return \Cubiche\Core\Async\Promise\PromiseInterface
35
     */
36
    public static function fulfilled($value = null)
37
    {
38
        return new FulfilledPromise($value);
39
    }
40
41
    /**
42
     * @param mixed $reason
43
     *
44
     * @return \Cubiche\Core\Async\Promise\PromiseInterface
45
     */
46
    public static function rejected($reason = null)
47
    {
48
        return new RejectedPromise($reason);
49
    }
50
51
    /**
52
     * @param PromiseInterface[] $promises
53
     *
54
     * @return \Cubiche\Core\Async\Promise\PromiseInterface
55
     */
56
    public static function all($promises)
57
    {
58
        return self::map($promises);
59
    }
60
61
    /**
62
     * @param PromiseInterface[] $promises
63
     * @param callable           $map
64
     *
65
     * @return \Cubiche\Core\Async\Promise\PromiseInterface
66
     */
67
    public static function map($promises, callable $map = null)
68
    {
69
        $pending = \count($promises);
70
        if ($pending == 0) {
71
            return self::fulfilled(array());
72
        }
73
74
        $deferred = self::defer();
75
        $results = array();
76
77
        /*
78
         * @var \Cubiche\Core\Async\Promise\PromiseInterface
79
         */
80
        foreach ($promises as $key => $promise) {
81
            $promise->then(
82
                function ($value) use ($deferred, &$results, $map, $key, &$pending) {
83
                    if ($map !== null) {
84
                        $value = $map($value);
85
                    }
86
                    $results[$key] = $value;
87
88
                    if (--$pending == 0) {
89
                        $deferred->resolve($results);
90
                    }
91
                },
92
                function ($reason) use ($deferred) {
93
                    $deferred->reject($reason);
94
                }
95
            );
96
        }
97
98
        return $deferred->promise();
99
    }
100
101
    /**
102
     * @param PromiseInterface $promise
103
     * @param int|float        $time
104
     * @param LoopInterface    $loop
105
     *
106
     * @return \Cubiche\Core\Async\Promise\PromiseInterface
107
     */
108
    public static function timeout(PromiseInterface $promise, $time, LoopInterface $loop)
109
    {
110
        $deferred = self::defer();
111
        $timer = $loop->timeout(
112
            function () use ($promise, $deferred, $time) {
113
                $deferred->reject(new TimeoutException($time));
114
            },
115
            $time
116
        );
117
118
        $promise->then(
119
            function ($value = null) use ($deferred, $timer) {
120
                $timer->cancel();
121
                $deferred->resolve($value);
122
            },
123
            function ($reason = null) use ($deferred, $timer) {
124
                $timer->cancel();
125
                $deferred->reject($reason);
126
            }
127
        );
128
129
        return $deferred->promise();
130
    }
131
132
    /**
133
     * @param PromiseInterface $promise
134
     * @param LoopInterface    $loop
135
     * @param int|float        $timeout
136
     *
137
     * @throws RejectionException
138
     *
139
     * @return mixed
140
     */
141
    public static function get(PromiseInterface $promise, LoopInterface $loop, $timeout = null)
142
    {
143
        $result = null;
144
        $rejectionReason = null;
145
        if ($timeout !== null) {
146
            $promise = self::timeout($promise, $timeout, $loop);
147
        }
148
149
        $promise->then(
150
            function ($value = null) use (&$result) {
151
                $result = $value;
152
            },
153
            function ($reason = null) use (&$rejectionReason) {
154
                $rejectionReason = $reason;
155
            }
156
        )->always(
157
            function () use ($loop) {
158
                $loop->stop();
159
            }
160
        );
161
162
        while ($promise->state()->equals(State::PENDING())) {
163
            $loop->run();
164
        }
165
166
        if ($promise->state()->equals(State::FULFILLED())) {
167
            return $result;
168
        }
169
170
        throw new RejectionException($rejectionReason);
171
    }
172
173
    /**
174
     * @param ThenableInterface $thenable
175
     *
176
     * @return \Cubiche\Core\Async\Promise\PromisorInterface
177
     */
178
    public static function promisor(ThenableInterface $thenable)
179
    {
180
        return new ThenablePromisor($thenable);
181
    }
182
}
183