Skip to content

Commit

Permalink
add promises
Browse files Browse the repository at this point in the history
Add promises to support awaiting async operations.
  • Loading branch information
bhcleek committed May 27, 2019
1 parent c70f333 commit 8ca22ee
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
50 changes: 50 additions & 0 deletions autoload/go/promise.vim
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
41 changes: 41 additions & 0 deletions autoload/go/promise_test.vim
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

0 comments on commit 8ca22ee

Please sign in to comment.