-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add promises to support awaiting async operations.
- Loading branch information
Showing
2 changed files
with
91 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
" don't spam the user when Vim is started in Vi compatibility mode | ||
let s:cpo_save = &cpo | ||
set cpo&vim | ||
|
||
scriptencoding utf-8 | ||
|
||
" New returns a promise. A promise's primary purpose is to make async jobs | ||
" synchronous by awaiting fn. | ||
" | ||
" A promise is a dictionary with two keys: | ||
" 'wrapper': | ||
" A function that wraps fn. It can be used in place of fn. | ||
" 'await': | ||
" A function that waits for wrapper to be called and returns the value | ||
" returned by fn. Returns default if timeout expires. | ||
function! go#promise#New(fn, timeout, default) abort | ||
let l:state = {} | ||
|
||
" explicitly bind to state so that within l:promise's methods, self will | ||
" always refer to state. See :help Partial for more information. | ||
return { | ||
\ 'wrapper': function('s:wrapper', [a:fn], l:state), | ||
\ 'await': function('s:await', [a:timeout, a:default], l:state), | ||
\ } | ||
endfunction | ||
|
||
function! s:wrapper(fn, ...) dict | ||
let self.retval = call(a:fn, a:000) | ||
return self.retval | ||
endfunction | ||
|
||
function! s:await(timeout, default) dict | ||
let l:timer = timer_start(a:timeout, function('s:setretval', [a:default], self)) | ||
while !has_key(self, 'retval') | ||
sleep 50m | ||
endwhile | ||
call timer_stop(l:timer) | ||
|
||
return self.retval | ||
endfunction | ||
|
||
function! s:setretval(val, timer) dict | ||
let self.retval = a:val | ||
endfunction | ||
|
||
" restore Vi compatibility settings | ||
let &cpo = s:cpo_save | ||
unlet s:cpo_save | ||
|
||
" vim: sw=2 ts=2 et |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
" don't spam the user when Vim is started in Vi compatibility mode | ||
let s:cpo_save = &cpo | ||
set cpo&vim | ||
|
||
func! Test_PromiseNew() abort | ||
let l:sut = go#promise#New(function('s:work', []), 100, -1) | ||
call assert_true(has_key(l:sut, 'wrapper')) | ||
call assert_true(has_key(l:sut, 'await')) | ||
endfunc | ||
|
||
func! Test_PromiseAwait() abort | ||
let l:expected = 1 | ||
let l:default = -1 | ||
let l:sut = go#promise#New(function('s:work', [l:expected]), 100, l:default) | ||
|
||
call timer_start(10, l:sut.wrapper) | ||
|
||
let l:actual = call(l:sut.await, []) | ||
call assert_equal(l:expected, l:actual) | ||
endfunc | ||
|
||
func! Test_PromiseAwait_Timeout() abort | ||
let l:desired = 1 | ||
let l:expected = -1 | ||
let l:sut = go#promise#New(function('s:work', [l:desired]), 10, l:expected) | ||
|
||
call timer_start(100, l:sut.wrapper) | ||
|
||
let l:actual = call(l:sut.await, []) | ||
call assert_equal(l:expected, l:actual) | ||
endfunc | ||
|
||
func! s:work(val, timer) | ||
return a:val | ||
endfunc | ||
|
||
" restore Vi compatibility settings | ||
let &cpo = s:cpo_save | ||
unlet s:cpo_save | ||
|
||
" vim: sw=2 ts=2 et |