promise.rb 0.2.1 → 0.3.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.
- data/.travis.yml +2 -2
- data/Gemfile +7 -0
- data/README.md +89 -3
- data/config/flay.yml +1 -1
- data/config/reek.yml +1 -1
- data/lib/promise.rb +17 -7
- data/lib/promise/version.rb +1 -1
- data/spec/promise_spec.rb +34 -2
- metadata +9 -5
- checksums.yaml +0 -15
data/.travis.yml
CHANGED
@@ -3,11 +3,11 @@ rvm:
|
|
3
3
|
- 1.9.3
|
4
4
|
- 2.0.0
|
5
5
|
- jruby-19mode
|
6
|
-
- rbx
|
6
|
+
- rbx
|
7
7
|
- ruby-head
|
8
8
|
- jruby-head
|
9
9
|
matrix:
|
10
10
|
allow_failures:
|
11
11
|
- rvm: ruby-head
|
12
12
|
- rvm: jruby-head
|
13
|
-
script: bundle exec rake
|
13
|
+
script: bundle exec rake -t metrics:coverage ci
|
data/Gemfile
CHANGED
@@ -9,5 +9,12 @@ gem 'fuubar', git: 'https://github.com/lgierth/fuubar.git',
|
|
9
9
|
ref: 'static-percentage'
|
10
10
|
gem 'awesome_print'
|
11
11
|
|
12
|
+
platform :rbx do
|
13
|
+
gem 'rubysl', '~> 2.0'
|
14
|
+
gem 'rubysl-json', '~> 2.0'
|
15
|
+
gem 'rubinius', '~> 2.0'
|
16
|
+
gem 'racc'
|
17
|
+
end
|
18
|
+
|
12
19
|
# Added by devtools
|
13
20
|
eval_gemfile 'Gemfile.devtools'
|
data/README.md
CHANGED
@@ -1,4 +1,90 @@
|
|
1
|
-
promise
|
2
|
-
=======
|
1
|
+
# promise.rb [](https://travis-ci.org/lgierth/promise.rb) [](https://codeclimate.com/github/lgierth/promise.rb) [](https://coveralls.io/r/lgierth/promise.rb?branch=master)
|
3
2
|
|
4
|
-
Promises/A+
|
3
|
+
Ruby implementation of the [Promises/A+ spec](http://promisesaplus.com/).
|
4
|
+
100% mutation coverage, tested on 1.9, 2.0, Rubinius, and JRuby.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'promise.rb'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install promise.rb
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
promise.rb doesn't come with a way of scheduling callback dispatch.
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
require 'promise'
|
26
|
+
|
27
|
+
class MyPromise < Promise
|
28
|
+
def defer(callback, arg)
|
29
|
+
callback.dispatch(arg)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
The above scheduling mechanism violates the following section of the spec:
|
35
|
+
|
36
|
+
> onFulfilled or onRejected must not be called until the execution context
|
37
|
+
> stack contains only platform code.
|
38
|
+
|
39
|
+
Compliance can be achieved, for example, by running an event reactor like
|
40
|
+
EventMachine:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
require 'promise'
|
44
|
+
require 'eventmachine'
|
45
|
+
|
46
|
+
class MyPromise < Promise
|
47
|
+
def defer(callback, arg)
|
48
|
+
EM.next_tick { callback.dispatch(arg) }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
Now you can create MyPromise objects, and fullfil (or reject) them, as well as
|
54
|
+
add callbacks to them:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
def nonblocking_stuff
|
58
|
+
promise = MyPromise.new
|
59
|
+
EM.next_tick { promise.fulfill('value') }
|
60
|
+
promise
|
61
|
+
end
|
62
|
+
|
63
|
+
nonblocking_stuff.then { |value| p value }
|
64
|
+
nonblocking_stuff.then(proc { |value| p value })
|
65
|
+
```
|
66
|
+
|
67
|
+
Rejection works similarly:
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
def failing_stuff
|
71
|
+
promise = MyPromise.new
|
72
|
+
EM.next_tick { promise.reject('reason') }
|
73
|
+
promise
|
74
|
+
end
|
75
|
+
|
76
|
+
failing_stuff.then(proc { |value| }, proc { |reason| p reason })
|
77
|
+
```
|
78
|
+
|
79
|
+
## License
|
80
|
+
|
81
|
+
Hatetepe is licensed under the [MIT License](http://opensource.org/licenses/MIT).
|
82
|
+
See LICENSE.txt for details.
|
83
|
+
|
84
|
+
## Contributing
|
85
|
+
|
86
|
+
1. Fork it
|
87
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
88
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
89
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
90
|
+
5. Create new Pull Request
|
data/config/flay.yml
CHANGED
data/config/reek.yml
CHANGED
data/lib/promise.rb
CHANGED
@@ -34,14 +34,20 @@ class Promise
|
|
34
34
|
next_promise
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
37
|
+
def sync
|
38
|
+
wait if pending?
|
39
|
+
fail reason if rejected?
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
def fulfill(value = nil)
|
38
44
|
dispatch(@on_fulfill, value) do
|
39
45
|
@state = :fulfilled
|
40
46
|
@value = value
|
41
47
|
end
|
42
48
|
end
|
43
49
|
|
44
|
-
def reject(reason)
|
50
|
+
def reject(reason = nil)
|
45
51
|
dispatch(@on_reject, reason) do
|
46
52
|
@state = :rejected
|
47
53
|
@reason = reason
|
@@ -61,7 +67,7 @@ class Promise
|
|
61
67
|
if pending?
|
62
68
|
yield
|
63
69
|
arg.freeze
|
64
|
-
callbacks.each { |callback|
|
70
|
+
callbacks.each { |callback| dispatch!(callback, arg) }
|
65
71
|
end
|
66
72
|
|
67
73
|
# Callback#assume_state uses #dispatch as returned_promise's on_fulfill
|
@@ -74,15 +80,19 @@ class Promise
|
|
74
80
|
|
75
81
|
def maybe_dispatch(fulfill_callback, reject_callback)
|
76
82
|
if fulfilled?
|
77
|
-
|
83
|
+
dispatch!(fulfill_callback, value)
|
78
84
|
end
|
79
85
|
|
80
86
|
if rejected?
|
81
|
-
|
87
|
+
dispatch!(reject_callback, reason)
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|
85
|
-
def
|
86
|
-
callback.dispatch(arg)
|
91
|
+
def dispatch!(callback, arg)
|
92
|
+
defer { callback.dispatch(arg) }
|
93
|
+
end
|
94
|
+
|
95
|
+
def defer
|
96
|
+
yield
|
87
97
|
end
|
88
98
|
end
|
data/lib/promise/version.rb
CHANGED
data/spec/promise_spec.rb
CHANGED
@@ -7,8 +7,12 @@ describe Promise do
|
|
7
7
|
|
8
8
|
let(:value) { double('value') }
|
9
9
|
let(:other_value) { double('other_value') }
|
10
|
-
let(:reason)
|
11
|
-
|
10
|
+
let(:reason) do
|
11
|
+
StandardError.new('reason').tap { |ex| ex.set_backtrace(caller) }
|
12
|
+
end
|
13
|
+
let(:other_reason) do
|
14
|
+
StandardError.new('other_reason').tap { |ex| ex.set_backtrace(caller) }
|
15
|
+
end
|
12
16
|
|
13
17
|
describe '3.1.1 pending' do
|
14
18
|
it 'transitions to fulfilled' do
|
@@ -337,11 +341,39 @@ describe Promise do
|
|
337
341
|
it 'does not return anything' do
|
338
342
|
expect(subject.fulfill(nil)).to eq(nil)
|
339
343
|
end
|
344
|
+
|
345
|
+
it 'does not require a value' do
|
346
|
+
subject.fulfill
|
347
|
+
expect(subject.value).to be(nil)
|
348
|
+
end
|
340
349
|
end
|
341
350
|
|
342
351
|
describe '#reject' do
|
343
352
|
it 'does not return anything' do
|
344
353
|
expect(subject.reject(nil)).to eq(nil)
|
345
354
|
end
|
355
|
+
|
356
|
+
it 'does not require a reason' do
|
357
|
+
subject.reject
|
358
|
+
expect(subject.reason).to be(nil)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
describe '#sync' do
|
363
|
+
it 'waits for fulfillment' do
|
364
|
+
allow(subject).to receive(:wait) { subject.fulfill(value) }
|
365
|
+
expect(subject.sync).to be(value)
|
366
|
+
end
|
367
|
+
|
368
|
+
it 'waits for rejection' do
|
369
|
+
allow(subject).to receive(:wait) { subject.reject(reason) }
|
370
|
+
expect { subject.sync }.to raise_error(reason)
|
371
|
+
end
|
372
|
+
|
373
|
+
it 'waits if pending' do
|
374
|
+
subject.fulfill(value)
|
375
|
+
expect(subject).not_to receive(:wait)
|
376
|
+
expect(subject.sync).to be(value)
|
377
|
+
end
|
346
378
|
end
|
347
379
|
end
|
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: promise.rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Lars Gierth
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-
|
12
|
+
date: 2013-12-07 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: rspec
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ! '>='
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :development
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ! '>='
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -56,26 +59,27 @@ files:
|
|
56
59
|
homepage: https://github.com/lgierth/promise
|
57
60
|
licenses:
|
58
61
|
- MIT
|
59
|
-
metadata: {}
|
60
62
|
post_install_message:
|
61
63
|
rdoc_options: []
|
62
64
|
require_paths:
|
63
65
|
- lib
|
64
66
|
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
65
68
|
requirements:
|
66
69
|
- - ! '>='
|
67
70
|
- !ruby/object:Gem::Version
|
68
71
|
version: '0'
|
69
72
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
70
74
|
requirements:
|
71
75
|
- - ! '>='
|
72
76
|
- !ruby/object:Gem::Version
|
73
77
|
version: '0'
|
74
78
|
requirements: []
|
75
79
|
rubyforge_project:
|
76
|
-
rubygems_version:
|
80
|
+
rubygems_version: 1.8.23
|
77
81
|
signing_key:
|
78
|
-
specification_version:
|
82
|
+
specification_version: 3
|
79
83
|
summary: Promises/A+ for Ruby
|
80
84
|
test_files:
|
81
85
|
- spec/promise_spec.rb
|
checksums.yaml
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
---
|
2
|
-
!binary "U0hBMQ==":
|
3
|
-
metadata.gz: !binary |-
|
4
|
-
NGFmYWVmYmRmNWEyMjkyYmMwY2Y0NjA2OWE1YzBjZTM2NTlkNzFmMA==
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ODg2NzU0ZjFmZTZjY2YzODFlYzJiYzUwMWE1OGQ2NWE4MGVlYTM0ZQ==
|
7
|
-
SHA512:
|
8
|
-
metadata.gz: !binary |-
|
9
|
-
NzA4MmZhMGJiNTliYWIxZjQ5NmY1YTc2NTE5ZTQzY2Y1MTEzNzEyZGVjY2Yy
|
10
|
-
MjdkODk5ZGYxMjMwMjZiYjUzODdmZmY2YzIxNDk1M2Y3ZWQ1M2RkMjdhY2Jl
|
11
|
-
MTRhNzY2M2E4NWExNjY1OTg3OTYzYmI2NzY0MzZlNDE3ZmI2YWY=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
N2MxOTAzZWMzMmUyNGY4MTVhODEwZWYwODNhNmRkYmMwYjU1MWNjNTI3ZGQz
|
14
|
-
MTZhZDliZWQyZWRjNmVkN2E4MDA5YzhhZjBmMDkxMTYxNTQzYTRkZWU3N2Ix
|
15
|
-
MTgyZGMyZTNiMjJiMTczZDRmNTA4ZjEzMDE2MDZhMjc4YmI4ZWY=
|