Skip to content

Instantly share code, notes, and snippets.

@south37
Last active September 14, 2016 02:23
Show Gist options
  • Save south37/5d992bd962cea56c450d to your computer and use it in GitHub Desktop.
Save south37/5d992bd962cea56c450d to your computer and use it in GitHub Desktop.
Ruby で ES7 の async/await を超絶簡単に実装する ref: http://qiita.com/south37/items/99a60345b22ef395d424
1 var request = require('./request.js');
2 var headers = { 'User-Agent': 'lukehoban', 'Authorization': 'token 665021d813ad67942206d94c47d7947716d27f66' };
3
4 // Promise-returning asynchronous function
5 async function getCollaboratorImages(full_name) {
6 // any exceptions thrown here will propogate into try/catch in callers - same as synchronous
7 var url = 'https://api.github.com/repos/' + full_name + '/collaborators';
8 // await a promise-returning async HTTP GET - same as synchronous
9 var [response, body] = await request({url: url, headers: headers});
10 return JSON.parse(body).map(function(collab) {
11 return collab.avatar_url;
12 });
13 }
// Promise版
1 var request = require('./request.js');
2 var headers = { 'User-Agent': 'lukehoban', 'Authorization': 'token 665021d813ad67942206d94c47d7947716d27f66' };
3
4 function getCollaboratorImages(full_name) {
5 var url = 'https://api.github.com/repos/' + full_name + '/collaborators';
6 return request({url: url, headers: headers}).then(function(value) {
7 var [response, body] = value;
8 JSON.parse(body).map(function(collab) {
9 return collab.avatar_url;
10 });
11 })
12 }
1 class Promise
2 def initialize(callback)
3 @callback = callback
4 end
5
6 def then(resolve = ->() {}, reject = ->() {})
7 @callback.call(resolve, reject)
8 end
9 end
1 require 'eventmachine'
2
3 def sleep(sec)
4 Promise.new(->(resolve, reject) {
5 EM.add_timer(sec) do
6 resolve.call('you sleep ' + sec.to_s)
7 end
8 })
9 end
10
11 EM.run do
12 sleep(0.3).then(->(value) {
13 p value
14 })
15 p 'start'
16 end
17 #=> "start"
18 #=> "you sleep 0.3"
1 def decorate_message(message)
2 Promise.new(->(resolve, reject) {
3 http = EM::HttpRequest.new('http://google.com/').get
4 http.callback {
5 resolve.call(message + ': ' + http.response[0..100])
6 }
7 })
8 end
# use Promise
1 def func(time)
2 sleep(time).then(->(message) {
3 p message
4 decorate_message(message).then(->(decorated_message) {
5 p decorated_message
6 })
7 })
8 end
9
10 EM.run do
11 func(0.3)
12 p 'start'
13 end
14 #=> "start"
15 #=> "you sleep 0.3"
16 #=> "you sleep 0.3: <HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>302 Moved</TITL"
# use async/await
1 async :asyncFunc do |time|
2 message = await sleep(time)
3 p message
4 decorate_message = await decorate_message(message)
5 p decorate_message
6 end
7
8 EM.run do
9 asyncFunc(0.3)
10 p 'start'
11 end
12 #=> "start"
13 #=> "you sleep 0.3"
14 #=> "you sleep 0.3: <HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>302 Moved</TITL"
# implementation of async/await
1 def async_internal(fiber)
2 chain = ->(result) {
3 return if result.class != Promise
4 result.then(->(val) {
5 chain.call(fiber.resume(val))
6 })
7 }
8 chain.call(fiber.resume)
9 end
10
11 def async(method_name, &block)
12 define_method method_name, ->(*args) {
13 async_internal(Fiber.new { block.call(*args) })
14 }
15 end
16
17 def await(promise)
18 Fiber.yield promise
19 end
# implementation of async/await
1 def async_internal(fiber)
2 chain = ->(result) {
3 return if result.class != Promise
4 result.then(->(val) {
5 chain.call(fiber.resume(val))
6 })
7 }
8 chain.call(fiber.resume)
9 end
10
11 def async(method_name, &block)
12 define_method method_name, ->(*args) {
13 async_internal(Fiber.new { block.call(*args) })
14 }
15 end
16
17 def await(promise)
18 Fiber.yield promise
19 end
# fiber example
1 fiber = Fiber.new do
2 p 'init fiber'
3 n = 0
4 loop do
5 result = Fiber.yield(n)
6 p "after yiled: #{result}"
7 n += 1
8 end
9 end
10
11 i = 10
12 4.times do
13 result = fiber.resume(i)
14 p "after resume: #{result}"
15 i += 1
16 end
17 # >> "init fiber"
18 # >> "after resume: 0"
19 # >> "after yiled: 11"
20 # >> "after resume: 1"
21 # >> "after yiled: 12"
22 # >> "after resume: 2"
23 # >> "after yiled: 13"
24 # >> "after resume: 3"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment