opal-async 1.1.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/README.md +100 -23
- data/VERSION +1 -1
- data/opal/async/ext.rb +3 -0
- data/opal/async/ext/array.rb +30 -0
- data/opal/async/ext/kernel.rb +11 -0
- data/opal/async/ext/thread.rb +17 -0
- data/opal/async/task.rb +22 -2
- metadata +26 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bcf44d0cb1a3c702b3c60521a2e173b7a3824fd8a37e80cd0fb18d5c4e0ffc2c
|
4
|
+
data.tar.gz: 28e4364132c94e690752669a3211796ec2b3423314a0db4892348d92fb0beb46
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 695a85e00e549b7616d7bf120e8651d574c8d42cf58e4483fd7e0a7a36581942836457ad2bdb08a03232217f7bb92434a6fa75cbac217f5498e545186ae66430
|
7
|
+
data.tar.gz: e4a46e19095d1017f93574d52f40a47ff5dfd85b290ce0acb5a885e2500eec44813acdb2f3ea683ef6813711e0f8ccbb4c5beaae0969e3a908e0cb7bd51cf1ab
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
## 1.4.0
|
4
|
+
|
5
|
+
- Drop `Array#cycle` and `Array#each` overrides and re-implement as `Array#async_cycle` and `Array#async_each`
|
6
|
+
- Asynchronous `Kernel#async_loop` alternative to `Kernel#loop`
|
7
|
+
|
8
|
+
## 1.3.0
|
9
|
+
|
10
|
+
- Asynchronous `Array#each` method that is web browser event loop friendly
|
11
|
+
- `Thread#kill` and `Thread#stop` for partial-compatibility with Ruby `Thread`
|
12
|
+
|
13
|
+
## 1.2.0
|
14
|
+
|
15
|
+
- Asynchronous `Array#cycle` method that is web browser event loop friendly
|
16
|
+
|
17
|
+
## 1.1.1
|
18
|
+
|
19
|
+
- Added `Thread` class extension to enable using `Async::Task` as `Thread` in Opal
|
20
|
+
|
21
|
+
## 1.1.0
|
22
|
+
|
23
|
+
- Initial version
|
data/README.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# Opal: Async
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/opal-async.svg)](https://badge.fury.io/rb/opal-async)
|
2
3
|
|
3
4
|
## Installation
|
4
5
|
|
5
6
|
Add this line to your application's Gemfile:
|
6
7
|
|
7
|
-
gem 'opal-async',
|
8
|
+
gem 'opal-async', '~> 1.3.0'
|
8
9
|
|
9
10
|
And then execute:
|
10
11
|
|
@@ -14,12 +15,11 @@ Or install it yourself as:
|
|
14
15
|
|
15
16
|
$ gem install opal-async
|
16
17
|
|
17
|
-
Then require 'opal-async' in both your Opal code and your Opal compilation environment.
|
18
|
-
|
18
|
+
Then require 'opal-async' in both your [Opal](https://opalrb.com/) code and your Opal compilation environment.
|
19
19
|
|
20
20
|
## Usage
|
21
21
|
|
22
|
-
|
22
|
+
### Enumerator
|
23
23
|
|
24
24
|
The enumerator provides iteration methods for any enumerable object. These methods are 'non-blocking', so other operations in the event loop can continue to be executed in between iterations. Beware, this is not faster than a normal blocking iteration; it is trading off performance for not blocking other operations you may want to have continue such as UI updates & camera frame capture. Very large arrays will take a long time to finish while the overhead may not be noticeable for smaller arrays. It is best to do some tests and assess whether the trade-off is balanced enough for your needs.
|
25
25
|
|
@@ -43,21 +43,21 @@ enumerator.map{|x| x + 2}.each_slice(3).each{|x| puts x}
|
|
43
43
|
#=> [9,10,11]
|
44
44
|
```
|
45
45
|
|
46
|
-
|
46
|
+
#### Available enumerator methods:
|
47
47
|
- each
|
48
48
|
- map
|
49
49
|
- each_slice
|
50
50
|
- select
|
51
51
|
- reject
|
52
52
|
|
53
|
-
|
53
|
+
### Task
|
54
54
|
A task contains code that will be added to the call stack of the event loop. The Enumerator uses tasks to run small chunks of code without blocking the event loop. A task can do the same things that a Timeout or an Interval can do but with some added features and optimizations.
|
55
55
|
|
56
56
|
With no options provided, a task will be run immediately once the event loop comes back to it(if the environment supports this). If the environment does not support immediates, it will attempt to polyfill an immediate before falling back on a 0ms timeout.
|
57
57
|
|
58
|
-
Example:
|
58
|
+
Example:
|
59
59
|
|
60
|
-
```
|
60
|
+
```ruby
|
61
61
|
Async::Task.new do
|
62
62
|
puts "hello world"
|
63
63
|
end
|
@@ -67,7 +67,7 @@ end
|
|
67
67
|
|
68
68
|
By default, a task will only run once. To make a task repeat, set the option times to however many times you want the task to repeat. You can also have access to countup and countdown variables.
|
69
69
|
|
70
|
-
```
|
70
|
+
```ruby
|
71
71
|
Async::Task.new do times: 5 do |countup, countdown|
|
72
72
|
puts countdown
|
73
73
|
end
|
@@ -77,11 +77,11 @@ end
|
|
77
77
|
#=> 3
|
78
78
|
#=> 2
|
79
79
|
#=> 1
|
80
|
-
```
|
80
|
+
```
|
81
81
|
|
82
82
|
To make a task repeat infinitely, set times to ```:infinite```, or repeat to ```true```. A countup will be provided but no countdown. You can also use ```:i``` for short.
|
83
83
|
|
84
|
-
```
|
84
|
+
```ruby
|
85
85
|
Async::Task.new times: :infinite do
|
86
86
|
puts "forever"
|
87
87
|
end
|
@@ -95,7 +95,7 @@ end
|
|
95
95
|
|
96
96
|
The step option will determine how much you want your task to "step".
|
97
97
|
|
98
|
-
```
|
98
|
+
```ruby
|
99
99
|
Async::Task.new times: 10, step: 2 do |countup, countdown|
|
100
100
|
puts countup
|
101
101
|
end
|
@@ -109,15 +109,15 @@ end
|
|
109
109
|
|
110
110
|
To set a delay time on your task, specify the delay option with the number of milliseconds you want the duration of the delay to be. This can also be done when you have set your task to repeat.
|
111
111
|
|
112
|
-
```
|
112
|
+
```ruby
|
113
113
|
Async::Task.new delay: 1000 do
|
114
114
|
puts "this took 1 second"
|
115
|
-
end
|
115
|
+
end
|
116
116
|
```
|
117
117
|
|
118
118
|
The delay and steps of a task can be modified within the execution of the task. The following example will start out slow and increase in speed:
|
119
119
|
|
120
|
-
```
|
120
|
+
```ruby
|
121
121
|
task = Async::Task.new times: 5, delay: 5000 do |countup, countdown|
|
122
122
|
puts countdown
|
123
123
|
task.delay = task.delay - 1000
|
@@ -128,7 +128,7 @@ Tasks also have callbacks that can be performed on certain events.
|
|
128
128
|
|
129
129
|
Here is an example of how to execute code after a repeating task has finished:
|
130
130
|
|
131
|
-
```
|
131
|
+
```ruby
|
132
132
|
task = Async::Task.new times: 3, delay: 1000 do |countup, countdown|
|
133
133
|
puts countdown
|
134
134
|
end
|
@@ -144,24 +144,101 @@ task.on_finish {puts "BOOM"}
|
|
144
144
|
Other callbacks include ```on_start``` and ```on_stop```.
|
145
145
|
|
146
146
|
|
147
|
-
|
147
|
+
### Other Timers
|
148
148
|
|
149
|
-
You can also timeouts and intervals specifically:
|
149
|
+
You can also set timeouts and intervals, specifically:
|
150
150
|
|
151
151
|
|
152
|
-
```
|
153
|
-
Timeout.new 3000 do
|
152
|
+
```ruby
|
153
|
+
Async::Timeout.new 3000 do
|
154
154
|
puts "I just waited 3 seconds."
|
155
155
|
end
|
156
156
|
```
|
157
157
|
|
158
|
-
```
|
159
|
-
Interval.new 3000 do
|
158
|
+
```ruby
|
159
|
+
Async::Interval.new 3000 do
|
160
160
|
puts "I'm going to do this every 3 seconds."
|
161
161
|
end
|
162
162
|
```
|
163
163
|
|
164
|
+
### Ruby Extensions
|
165
|
+
|
166
|
+
[opal-async](https://rubygems.org/gems/opal-async) ships with some Opal Ruby extensions that enhance Ruby classes with asynchronous capabilities.
|
167
|
+
|
168
|
+
You may activate all the Ruby extensions via this require statement:
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
require 'async/ext'
|
172
|
+
```
|
173
|
+
|
174
|
+
#### Thread
|
175
|
+
|
176
|
+
You may use the `Async::Task` class as a `Thread` class in Opal to perform asynchronous work with an extra `require` statement.
|
177
|
+
|
178
|
+
```ruby
|
179
|
+
require 'async/ext/thread' # not needed if you called `require 'async/ext'`
|
180
|
+
|
181
|
+
Thread.new do
|
182
|
+
puts "hello world"
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
186
|
+
#### Array
|
187
|
+
|
188
|
+
The follow `Array` methods have been added to work asynchronously via `Async::Task`:
|
189
|
+
- `Array#async_cycle`
|
190
|
+
- `Array#async_each`
|
191
|
+
|
192
|
+
This makes them not block the web browser event loop, thus allowing other tasks to update the DOM unhindered while running.
|
193
|
+
|
194
|
+
Example:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
require 'async/ext/array' # not needed if you called `require 'async/ext'`
|
198
|
+
|
199
|
+
Async::Task.new do
|
200
|
+
[1,2,3,4].async_cycle do |n|
|
201
|
+
puts n
|
202
|
+
Async::Task.new do
|
203
|
+
# make a DOM update that is not blocked
|
204
|
+
end
|
205
|
+
sleep(1)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
```
|
209
|
+
|
210
|
+
#### Kernel
|
211
|
+
|
212
|
+
The follow `Kernel` method has been added to work asynchronously via `Async::Task`:
|
213
|
+
- `Array#async_loop`
|
214
|
+
|
215
|
+
This makes it not block the web browser event loop, thus allowing other tasks to update the DOM unhindered while running.
|
216
|
+
|
217
|
+
Example:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
require 'async/ext/kernel' # not needed if you called `require 'async/ext'`
|
221
|
+
|
222
|
+
Async::Task.new do
|
223
|
+
async_loop do
|
224
|
+
Async::Task.new do
|
225
|
+
# make a DOM update that is not blocked
|
226
|
+
end
|
227
|
+
sleep(1)
|
228
|
+
end
|
229
|
+
end
|
230
|
+
```
|
231
|
+
|
232
|
+
## In The Wild
|
233
|
+
|
234
|
+
opal-async is currently used in:
|
235
|
+
- [Glimmer DSL for Opal](https://github.com/AndyObtiva/glimmer-dsl-opal)
|
236
|
+
|
237
|
+
## Change Log
|
238
|
+
|
239
|
+
[CHANGELOG.md](CHANGELOG.md)
|
240
|
+
|
164
241
|
## Contributors
|
165
242
|
|
166
243
|
- [Benjamin Titcomb](https://github.com/Ravenstine) (Creator and Main Contributor)
|
167
|
-
- [Andy Maleh](https://github.com/AndyObtiva) (Gemifier)
|
244
|
+
- [Andy Maleh](https://github.com/AndyObtiva) (Gemifier and Maintainer)
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0
|
data/opal/async/ext.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'async/task'
|
2
|
+
|
3
|
+
class Array
|
4
|
+
def async_cycle(n=nil, &block)
|
5
|
+
array = self * n unless n.nil?
|
6
|
+
index = 0
|
7
|
+
looper = lambda do
|
8
|
+
if n.nil?
|
9
|
+
block.call(self[index])
|
10
|
+
index += 1
|
11
|
+
index = index % self.size
|
12
|
+
Async::Task.new(&looper)
|
13
|
+
else
|
14
|
+
block.call(array.shift)
|
15
|
+
Async::Task.new(&looper) unless array.empty?
|
16
|
+
end
|
17
|
+
end
|
18
|
+
Async::Task.new(&looper)
|
19
|
+
end
|
20
|
+
|
21
|
+
def async_each(&block)
|
22
|
+
array = self
|
23
|
+
index = 0
|
24
|
+
looper = lambda do
|
25
|
+
block.call(array.shift)
|
26
|
+
Async::Task.new(&looper) unless array.empty?
|
27
|
+
end
|
28
|
+
Async::Task.new(&looper)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'thread' # bring the thread compatibility class from Opal first
|
2
|
+
|
3
|
+
class Thread
|
4
|
+
def initialize(*args, &proc)
|
5
|
+
@async_task = Async::Task.new do
|
6
|
+
proc.call(*args)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def stop
|
11
|
+
@async_task.stop
|
12
|
+
end
|
13
|
+
|
14
|
+
def kill
|
15
|
+
@async_task.stop
|
16
|
+
end
|
17
|
+
end
|
data/opal/async/task.rb
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
module Async
|
2
2
|
class Task
|
3
|
+
class << self
|
4
|
+
# returns general status of whether a task is running.
|
5
|
+
# Useful to code running in the task block to determine if it is running
|
6
|
+
# as part of a task or not and take special actions accordingly.
|
7
|
+
def started?
|
8
|
+
@@started = false unless defined? :@@started
|
9
|
+
@@started
|
10
|
+
end
|
11
|
+
|
12
|
+
def start
|
13
|
+
@@started = true
|
14
|
+
end
|
15
|
+
|
16
|
+
def stop
|
17
|
+
@@started = false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
3
21
|
attr_accessor :delay, :times
|
4
22
|
def initialize options={}, &block
|
5
23
|
@options = options
|
@@ -15,6 +33,7 @@ module Async
|
|
15
33
|
@delay = @options[:delay] || 0
|
16
34
|
@times = @options[:times]
|
17
35
|
@proc = Proc.new do
|
36
|
+
self.class.start
|
18
37
|
if @times
|
19
38
|
if @times.is_a?(Fixnum)
|
20
39
|
@block.call(@countup, @countdown)
|
@@ -34,6 +53,7 @@ module Async
|
|
34
53
|
@block.call
|
35
54
|
@stopped = true
|
36
55
|
end
|
56
|
+
self.class.stop
|
37
57
|
end
|
38
58
|
end
|
39
59
|
|
@@ -110,9 +130,9 @@ module Async
|
|
110
130
|
};
|
111
131
|
var mc = new MessageChannel();
|
112
132
|
|
113
|
-
mc.port1.onmessage = function(){
|
133
|
+
mc.port1.onmessage = function(){
|
114
134
|
if (!#{stopped?}){
|
115
|
-
task.apply(task)
|
135
|
+
task.apply(task)
|
116
136
|
}
|
117
137
|
};
|
118
138
|
mc.port2.postMessage(null);
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: opal-async
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ravenstine
|
8
8
|
- Andy Maleh
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2021-08-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: opal
|
@@ -101,6 +101,20 @@ dependencies:
|
|
101
101
|
- - ">="
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: rake-tui
|
106
|
+
requirement: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
type: :development
|
112
|
+
prerelease: false
|
113
|
+
version_requirements: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
104
118
|
description: Provides non-blocking tasks and enumerators for Opal.
|
105
119
|
email:
|
106
120
|
- benjamin@pixelstreetinc.com
|
@@ -108,9 +122,11 @@ email:
|
|
108
122
|
executables: []
|
109
123
|
extensions: []
|
110
124
|
extra_rdoc_files:
|
125
|
+
- CHANGELOG.md
|
111
126
|
- LICENSE.txt
|
112
127
|
- README.md
|
113
128
|
files:
|
129
|
+
- CHANGELOG.md
|
114
130
|
- LICENSE.txt
|
115
131
|
- README.md
|
116
132
|
- VERSION
|
@@ -119,6 +135,10 @@ files:
|
|
119
135
|
- opal/async.rb
|
120
136
|
- opal/async/countdown.rb
|
121
137
|
- opal/async/enumerator.rb
|
138
|
+
- opal/async/ext.rb
|
139
|
+
- opal/async/ext/array.rb
|
140
|
+
- opal/async/ext/kernel.rb
|
141
|
+
- opal/async/ext/thread.rb
|
122
142
|
- opal/async/interval.rb
|
123
143
|
- opal/async/task.rb
|
124
144
|
- opal/async/timeout.rb
|
@@ -127,7 +147,7 @@ homepage: http://github.com/AndyObtiva/opal-async
|
|
127
147
|
licenses:
|
128
148
|
- MIT
|
129
149
|
metadata: {}
|
130
|
-
post_install_message:
|
150
|
+
post_install_message:
|
131
151
|
rdoc_options:
|
132
152
|
- "--main"
|
133
153
|
- README
|
@@ -147,8 +167,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
147
167
|
- !ruby/object:Gem::Version
|
148
168
|
version: '0'
|
149
169
|
requirements: []
|
150
|
-
rubygems_version: 3.1.
|
151
|
-
signing_key:
|
170
|
+
rubygems_version: 3.1.4
|
171
|
+
signing_key:
|
152
172
|
specification_version: 4
|
153
173
|
summary: Provides non-blocking tasks and enumerators for Opal.
|
154
174
|
test_files: []
|