Completed
Push — master ( 298e09...565401 )
by Ivannis Suárez
02:36
created

Promises::map()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 31
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 31
rs 8.439
cc 5
eloc 17
nc 3
nop 2
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
        /** @var \Cubiche\Core\Async\Promise\PromiseInterface $promise */
78
        foreach ($promises as $key => $promise) {
79
            $promise->then(
80
                function ($value) use ($deferred, &$results, $map, $key, &$pending) {
81
                    if ($map !== null) {
82
                        $value = $map($value);
83
                    }
84
                    $results[$key] = $value;
85
86
                    if (--$pending == 0) {
87
                        $deferred->resolve($results);
88
                    }
89
                },
90
                function ($reason) use ($deferred) {
91
                    $deferred->reject($reason);
92
                }
93
            );
94
        }
95
96
        return $deferred->promise();
97
    }
98
99
    /**
100
     * @param PromiseInterface $promise
101
     * @param int|float        $time
102
     * @param LoopInterface    $loop
103
     *
104
     * @return \Cubiche\Core\Async\Promise\PromiseInterface
105
     */
106
    public static function timeout(PromiseInterface $promise, $time, LoopInterface $loop)
107
    {
108
        $deferred = self::defer();
109
        $timer = $loop->timeout(function () use ($promise, $deferred, $time) {
110
            $deferred->reject(new TimeoutException($time));
111
        }, $time);
112
113
        $promise->then(function ($value = null) use ($deferred, $timer) {
114
            $timer->cancel();
115
            $deferred->resolve($value);
116
        }, function ($reason = null) use ($deferred, $timer) {
117
            $timer->cancel();
118
            $deferred->reject($reason);
119
        });
120
121
        return $deferred->promise();
122
    }
123
124
    /**
125
     * @param PromiseInterface $promise
126
     * @param LoopInterface    $loop
127
     * @param int|float        $timeout
128
     *
129
     * @throws RejectionException
130
     *
131
     * @return mixed
132
     */
133
    public static function get(PromiseInterface $promise, LoopInterface $loop, $timeout = null)
134
    {
135
        $result = null;
136
        $rejectionReason = null;
137
        if ($timeout !== null) {
138
            $promise = self::timeout($promise, $timeout, $loop);
139
        }
140
141
        $promise->then(function ($value = null) use (&$result) {
142
            $result = $value;
143
        }, function ($reason = null) use (&$rejectionReason) {
144
            $rejectionReason = $reason;
145
        })->always(function () use ($loop) {
146
            $loop->stop();
147
        });
148
149
        while ($promise->state()->equals(State::PENDING())) {
150
            $loop->run();
151
        }
152
153
        if ($promise->state()->equals(State::FULFILLED())) {
154
            return $result;
155
        }
156
157
        throw new RejectionException($rejectionReason);
158
    }
159
}
160