Now there is another problem. I hope I can write the code like this: 
    
    
    proc ff1(p1: int): Result =
       # my db acess code here
       ......
    
    proc ff2(p1, p2: int): Result =
       # my db acess code here
       ......
    
    proc main() {.async.} =
       # async call ff1 with parameter
       let r1 = await callAsync(ff1(1))
       
       # async call ff2 with parameter
       let r2 = await callAsync(ff2(1, 2))
       ......
    

Because we pass the parameter 'ff1(1)' to callAsync, so callAsync must be a 
macro like this: 
    
    
    macro callAsync*(p: untyped): untyped {.async.} =
       quote do:
          proc callme(evt: AsyncEvent): Result =
             let s = `p`
             evt.trigger()
             s
          
          let evt = newAsyncEvent()
          let fut = waitEvent(evt)
          let val = spawn callme(evt)
          await fut
          return ^val
    

But a macro cannot be {.async.}, so I cannot do this.

A limited way to resolve this problem is use an procval, here is the code: 
    
    
    type
       Result* = ref object of RootObj
          body*: string
       Action = proc(): Result
    
    proc waitEvent(evt: AsyncEvent): Future[void] =
       let fut = newFuture[void]("callAsync")
       addEvent(evt, (fd: AsyncFD) => (fut.complete(); true))
       return fut
    
    proc callp(evt: AsyncEvent, p: Action): Result =
       let v = p()
       evt.trigger()
       v
    
    proc callAsync*(p: Action): Future[Result] {.async.} =
       let evt = newAsyncEvent()
       let fut = waitEvent(evt)
       let val = spawn callp(evt, p)
       await fut
       return ^val
    
    proc ff(): Result =
       echo "work"
       sleep(1000)
       Result(body: "hello")
    
    block:
       let val = waitFor callAsync(ff)
       echo "future return ", val.body
    

The limitation is I can only call Action type proc, and I cannot pass the 
paramter freely.

Any way to solve the problem? Thanks.

Reply via email to