rpromise 0.0.5 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +99 -26
- data/lib/rpromise/version.rb +1 -1
- data/lib/rpromise.rb +10 -9
- data/rpromise.gemspec +1 -0
- data/spec/lib/rpromise_spec.rb +95 -144
- data/spec/spec_helper.rb +3 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f827fadaed28b188d96a603fd46c933e06f52e6f
|
4
|
+
data.tar.gz: b76fde2e1c6388e4ca470e4eb8a0a28f779fa9cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8b692957a78f776851bb84e5071304b7dd4a9666a9d8b44dd5254e336e7be3ebd82344ac60d98029961ca2cbcbe205ae97e04517d657a9a2c197a65f0e449cc
|
7
|
+
data.tar.gz: e968d06a23ee237efa58935cb4e5b80130c86821c52f2ab1f2cd2055f2fa8c8e87b4103e798eea821eaea5971eedb24d1e11f68f33312d7b9244c0293ed7fd4b
|
data/README.md
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# Rpromise
|
2
2
|
|
3
3
|
[](https://travis-ci.org/samuelmolinari/rpromise)
|
4
|
+
[](http://badge.fury.io/rb/rpromise)
|
5
|
+
[](https://codeclimate.com/github/samuelmolinari/rpromise)
|
6
|
+
[](https://codeclimate.com/github/samuelmolinari/rpromise)
|
4
7
|
|
5
8
|
## Installation
|
6
9
|
|
@@ -18,50 +21,120 @@ Or install it yourself as:
|
|
18
21
|
|
19
22
|
## Usage
|
20
23
|
|
24
|
+
### Create a promise
|
25
|
+
|
21
26
|
```ruby
|
22
27
|
|
23
28
|
class Task
|
24
29
|
|
25
30
|
def async
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
reject.call('Oh boy, what have you done')
|
35
|
-
end
|
31
|
+
::Rpromise.new do |resolve, reject|
|
32
|
+
sleep(1)
|
33
|
+
value = Random.rand * 10
|
34
|
+
|
35
|
+
if value > 5
|
36
|
+
resolve.call(value)
|
37
|
+
else
|
38
|
+
reject.call('Oh boy, what have you done')
|
36
39
|
end
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
40
43
|
end
|
41
44
|
|
42
|
-
|
45
|
+
```
|
43
46
|
|
44
|
-
|
47
|
+
### Callbacks
|
45
48
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
#### Using method
|
50
|
+
|
51
|
+
You can use existing methods as callbacks:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
def on_resolve(value)
|
55
|
+
# Do something with the returned value from the promise
|
53
56
|
end
|
54
57
|
|
55
|
-
|
56
|
-
|
58
|
+
Task.new.async.then(method(:on_resolve))
|
59
|
+
```
|
60
|
+
|
61
|
+
#### Using proc
|
62
|
+
|
63
|
+
You can use ``Proc`` as a callback
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
Task.new.async.then(Proc.new do |value|
|
67
|
+
# Do something
|
68
|
+
end)
|
69
|
+
```
|
70
|
+
|
71
|
+
#### Using lambda
|
72
|
+
|
73
|
+
You can use ``lambda`` as a callback
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
Task.new.async.then(lambda do |value|
|
77
|
+
# Do something
|
78
|
+
end)
|
79
|
+
```
|
80
|
+
|
81
|
+
### Chained promises
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
Rpromise.new do |resolve, reject|
|
85
|
+
|
86
|
+
resolve.call(5)
|
87
|
+
|
88
|
+
end.then(lambda do |value|
|
89
|
+
|
90
|
+
# value == 5
|
91
|
+
value + 10
|
92
|
+
|
93
|
+
end).then(lambda do |value|
|
94
|
+
|
95
|
+
# value == 15
|
96
|
+
Rpromise.new do |resolve, reject|
|
97
|
+
resolve.call(value / 5)
|
98
|
+
end
|
99
|
+
|
100
|
+
end).then(lambda do |value|
|
101
|
+
|
102
|
+
# value == 3
|
103
|
+
|
104
|
+
end)
|
105
|
+
```
|
106
|
+
|
107
|
+
#### Error handling
|
108
|
+
|
109
|
+
You can handle errors raised during the async task by passing a callback block as second argument
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
p = Rpromise.new do |resolve, reject|
|
113
|
+
raise 'Oopss'
|
57
114
|
end
|
58
115
|
|
59
|
-
|
60
|
-
.
|
61
|
-
|
62
|
-
|
63
|
-
|
116
|
+
p.then(nil, lambda do |err|
|
117
|
+
err.message # => "Oopss"
|
118
|
+
end)
|
119
|
+
```
|
120
|
+
|
121
|
+
or you can handle the exceptions yourself by making use of the reject callback
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
p = Rpromise.new do |resolve, reject|
|
125
|
+
begin
|
126
|
+
method_that_could_raise_an_exception()
|
127
|
+
resolve('Everything went ok')
|
128
|
+
rescue Exception => e
|
129
|
+
reject.call('Oh dear, what have I done?!')
|
130
|
+
end
|
131
|
+
end
|
64
132
|
|
133
|
+
p.then(lambda do |message|
|
134
|
+
# Called if the promise executed without exceptions
|
135
|
+
end, lambda do |err|
|
136
|
+
# Called if the promise has raised an exception
|
137
|
+
end)
|
65
138
|
```
|
66
139
|
|
67
140
|
## Contributing
|
data/lib/rpromise/version.rb
CHANGED
data/lib/rpromise.rb
CHANGED
@@ -9,12 +9,18 @@ class Rpromise
|
|
9
9
|
|
10
10
|
Handler = Struct.new(:on_resolved, :on_rejected, :resolve, :reject)
|
11
11
|
|
12
|
-
attr_reader :state
|
12
|
+
attr_reader :state, :thread
|
13
13
|
|
14
14
|
def initialize()
|
15
15
|
@state = State::PENDING
|
16
16
|
@defered = nil
|
17
|
-
|
17
|
+
@thread = Thread.new do
|
18
|
+
begin
|
19
|
+
yield(method(:resolve!), method(:reject!))
|
20
|
+
rescue Exception => e
|
21
|
+
reject!(e)
|
22
|
+
end
|
23
|
+
end
|
18
24
|
rescue Exception => e
|
19
25
|
reject!(e)
|
20
26
|
end
|
@@ -23,9 +29,9 @@ class Rpromise
|
|
23
29
|
raise ArgumentError unless is_valid_block?(on_resolved)
|
24
30
|
raise ArgumentError unless is_valid_block?(on_rejected)
|
25
31
|
return self if on_resolved.nil? && on_rejected.nil?
|
26
|
-
return ::Rpromise.new do |resolve, reject
|
32
|
+
return ::Rpromise.new do |resolve, reject|
|
27
33
|
handler = Handler.new(on_resolved, on_rejected, resolve, reject)
|
28
|
-
|
34
|
+
handle(handler)
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
@@ -53,9 +59,6 @@ class Rpromise
|
|
53
59
|
unless @defered.nil?
|
54
60
|
handle(@defered)
|
55
61
|
end
|
56
|
-
|
57
|
-
rescue
|
58
|
-
reject!(nil)
|
59
62
|
end
|
60
63
|
|
61
64
|
def reject!(value = nil)
|
@@ -92,7 +95,5 @@ class Rpromise
|
|
92
95
|
output = callback.call(@value)
|
93
96
|
handler.resolve.call(output) unless handler.resolve.nil?
|
94
97
|
end
|
95
|
-
rescue
|
96
|
-
handler.reject.call(nil) unless handler.reject.nil?
|
97
98
|
end
|
98
99
|
end
|
data/rpromise.gemspec
CHANGED
data/spec/lib/rpromise_spec.rb
CHANGED
@@ -12,30 +12,27 @@ describe ::Rpromise do
|
|
12
12
|
|
13
13
|
describe '#initialize' do
|
14
14
|
it 'uses the resolve! method as callback' do
|
15
|
-
|
15
|
+
lock = true
|
16
16
|
p = described_class.new do |resolve, reject|
|
17
|
-
|
18
|
-
|
19
|
-
end
|
17
|
+
resolve.call('hi')
|
18
|
+
lock = false
|
20
19
|
end
|
21
|
-
|
20
|
+
loop { break unless lock }
|
22
21
|
expect(p).to be_resolved
|
23
22
|
end
|
24
23
|
|
25
24
|
it 'uses the reject! method as callback' do
|
26
|
-
|
25
|
+
lock = true
|
27
26
|
p = described_class.new do |resolve, reject|
|
28
|
-
|
29
|
-
|
30
|
-
end
|
27
|
+
reject.call('hi')
|
28
|
+
lock = false
|
31
29
|
end
|
32
|
-
|
30
|
+
loop { break unless lock }
|
33
31
|
expect(p).to be_rejected
|
34
32
|
end
|
35
33
|
end
|
36
34
|
|
37
35
|
describe '#then' do
|
38
|
-
|
39
36
|
it 'returns a new promise' do
|
40
37
|
expect(promise.then).to be_kind_of described_class
|
41
38
|
end
|
@@ -58,158 +55,112 @@ describe ::Rpromise do
|
|
58
55
|
let(:value2) { Random.rand + value }
|
59
56
|
let(:value3) { Random.rand + value + value2 }
|
60
57
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@promise = described_class.new do |resolve, reject|
|
65
|
-
@thread = Thread.new do
|
66
|
-
sleep(0.5)
|
67
|
-
resolve.call(value)
|
68
|
-
end
|
69
|
-
end
|
58
|
+
before(:each) do
|
59
|
+
@promise = described_class.new do |resolve, reject|
|
60
|
+
resolve.call(value)
|
70
61
|
end
|
62
|
+
end
|
71
63
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
64
|
+
it 'returns the resolved value' do
|
65
|
+
lambda_value = nil
|
66
|
+
lock = true
|
67
|
+
@promise.then(lambda do |v|
|
68
|
+
lambda_value = v
|
69
|
+
lock = false
|
70
|
+
end)
|
71
|
+
loop { break unless lock }
|
72
|
+
expect(@promise).to be_resolved
|
73
|
+
expect(lambda_value).to eq value
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when multiple then are chained together' do
|
77
|
+
it 'passes its returned value to the next then' do
|
78
|
+
lambda_value_1 = nil
|
79
|
+
lambda_value_2 = nil
|
80
|
+
lambda_value_3 = nil
|
81
|
+
lock = true
|
82
|
+
@promise.then(lambda do |v1|
|
83
|
+
lambda_value_1 = v1
|
84
|
+
return value2
|
85
|
+
end).then(lambda do |v2|
|
86
|
+
lambda_value_2 = v2
|
87
|
+
return value3
|
88
|
+
end).then(lambda do |v3|
|
89
|
+
lambda_value_3 = v3
|
90
|
+
lock = false
|
76
91
|
end)
|
77
|
-
|
78
|
-
expect(
|
79
|
-
|
80
|
-
expect(
|
81
|
-
expect(lambda_value).to eq value
|
82
|
-
end
|
83
|
-
context 'when multiple then are chained together' do
|
84
|
-
it 'passes its returned value to the next then' do
|
85
|
-
lambda_value_1 = nil
|
86
|
-
lambda_value_2 = nil
|
87
|
-
lambda_value_3 = nil
|
88
|
-
@promise.then(lambda do |v1|
|
89
|
-
lambda_value_1 = v1
|
90
|
-
return value2
|
91
|
-
end).then(lambda do |v2|
|
92
|
-
lambda_value_2 = v2
|
93
|
-
return value3
|
94
|
-
end).then(lambda do |v3|
|
95
|
-
lambda_value_3 = v3
|
96
|
-
end)
|
97
|
-
@thread.join
|
98
|
-
expect(lambda_value_1).to eq value
|
99
|
-
expect(lambda_value_2).to eq value2
|
100
|
-
expect(lambda_value_3).to eq value3
|
101
|
-
end
|
102
|
-
end
|
103
|
-
context 'when then resolve callback returns a promise' do
|
104
|
-
it 'uses the next then as handler' do
|
105
|
-
thread2 = nil
|
106
|
-
lambda_value = nil
|
107
|
-
lock = true
|
108
|
-
@promise.then(lambda do |v|
|
109
|
-
return described_class.new do |resolve, reject|
|
110
|
-
thread2 = Thread.new do
|
111
|
-
sleep(0)
|
112
|
-
resolve.call('Hello world!')
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end).then(lambda do |hello_world|
|
116
|
-
lambda_value = hello_world
|
117
|
-
lock = false
|
118
|
-
end)
|
119
|
-
loop { break unless lock }
|
120
|
-
expect(lambda_value).to eq 'Hello world!'
|
121
|
-
end
|
122
|
-
end
|
123
|
-
context 'when no callback is passed' do
|
124
|
-
it 'passes original returned value to the next then' do
|
125
|
-
lambda_value = nil
|
126
|
-
@promise.then.then(lambda do |v|
|
127
|
-
lambda_value = v
|
128
|
-
end)
|
129
|
-
@thread.join
|
130
|
-
expect(lambda_value).to eq value
|
131
|
-
end
|
92
|
+
loop { break unless lock }
|
93
|
+
expect(lambda_value_1).to eq value
|
94
|
+
expect(lambda_value_2).to eq value2
|
95
|
+
expect(lambda_value_3).to eq value3
|
132
96
|
end
|
133
97
|
end
|
134
98
|
|
135
|
-
context '
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
99
|
+
context 'when then resolve callback returns a promise' do
|
100
|
+
it 'uses the next then as handler' do
|
101
|
+
thread2 = nil
|
102
|
+
lambda_value = nil
|
103
|
+
lock = true
|
104
|
+
@promise.then(lambda do |v|
|
105
|
+
return described_class.new do |resolve, reject|
|
106
|
+
thread2 = Thread.new do
|
107
|
+
resolve.call('Hello world!')
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end).then(lambda do |hello_world|
|
111
|
+
lambda_value = hello_world
|
112
|
+
lock = false
|
113
|
+
end)
|
114
|
+
loop { break unless lock }
|
115
|
+
expect(lambda_value).to eq 'Hello world!'
|
140
116
|
end
|
117
|
+
end
|
141
118
|
|
142
|
-
|
119
|
+
context 'when no callback is passed' do
|
120
|
+
it 'passes original returned value to the next then' do
|
143
121
|
lambda_value = nil
|
144
|
-
|
122
|
+
lock = true
|
123
|
+
@promise.then.then(lambda do |v|
|
145
124
|
lambda_value = v
|
125
|
+
lock = false
|
146
126
|
end)
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
context 'when multiple then are chained together' do
|
151
|
-
it 'passes its returned value to the next then' do
|
152
|
-
lambda_value_1 = nil
|
153
|
-
lambda_value_2 = nil
|
154
|
-
lambda_value_3 = nil
|
155
|
-
promise.then(lambda do |v1|
|
156
|
-
lambda_value_1 = v1
|
157
|
-
return value2
|
158
|
-
end).then(lambda do |v2|
|
159
|
-
lambda_value_2 = v2
|
160
|
-
return value3
|
161
|
-
end).then(lambda do |v3|
|
162
|
-
lambda_value_3 = v3
|
163
|
-
end)
|
164
|
-
expect(lambda_value_1).to eq value
|
165
|
-
expect(lambda_value_2).to eq value2
|
166
|
-
expect(lambda_value_3).to eq value3
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
context 'when no callback is passed' do
|
171
|
-
it 'does not raise any error' do
|
172
|
-
expect { promise.then }.not_to raise_error
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'passes original returned value to the next then' do
|
176
|
-
lambda_value = nil
|
177
|
-
promise.then.then(lambda do |v|
|
178
|
-
lambda_value = v
|
179
|
-
end)
|
180
|
-
expect(lambda_value).to eq value
|
181
|
-
end
|
127
|
+
loop { break unless lock }
|
128
|
+
expect(lambda_value).to eq value
|
182
129
|
end
|
183
130
|
end
|
184
131
|
end
|
185
132
|
|
186
133
|
context 'when promise is rejected' do
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
134
|
+
let(:error) { Random.rand }
|
135
|
+
it 'returns exception' do
|
136
|
+
lambda_error = nil
|
137
|
+
lock = true
|
138
|
+
p = described_class.new do |resolve, reject|
|
139
|
+
reject.call(error)
|
193
140
|
end
|
194
|
-
|
195
|
-
lambda_error =
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
promise.then(nil, lambda do |e|
|
207
|
-
lambda_error = e
|
208
|
-
end)
|
209
|
-
expect(lambda_error).to be_kind_of RuntimeError
|
210
|
-
expect(lambda_error.message).to eq 'Oops'
|
141
|
+
p.then(nil, lambda do |e|
|
142
|
+
lambda_error = e
|
143
|
+
lock = false
|
144
|
+
end)
|
145
|
+
loop { break unless lock }
|
146
|
+
expect(lambda_error).to eq error
|
147
|
+
end
|
148
|
+
it 'handles raised exceptions within the promise' do
|
149
|
+
lambda_error = nil
|
150
|
+
lock = true
|
151
|
+
p = described_class.new do |resolve, reject|
|
152
|
+
raise 'Oops'
|
211
153
|
end
|
154
|
+
p.then(nil, lambda do |e|
|
155
|
+
lambda_error = e
|
156
|
+
lock = false
|
157
|
+
end)
|
158
|
+
loop { break unless lock }
|
159
|
+
expect(lambda_error).to be_kind_of RuntimeError
|
160
|
+
expect(lambda_error.message).to eq 'Oops'
|
212
161
|
end
|
162
|
+
xit 'handles raised exceptions within resolve!'
|
163
|
+
xit 'handles raised exceptions within handle!'
|
213
164
|
end
|
214
165
|
end
|
215
166
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rpromise
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Molinari
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-11-
|
11
|
+
date: 2014-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: codeclimate-test-reporter
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description: Handle async method easily
|
84
98
|
email:
|
85
99
|
- samuel@molinari.me
|