Implementing Promise with Channels in Go

A different approach without using channels, which makes it a little bit faster / more efficient:

type Promise struct {
    wg  sync.WaitGroup
    res string
    err error
}

func NewPromise(f func() (string, error)) *Promise {
    p := &Promise{}
    p.wg.Add(1)
    go func() {
        p.res, p.err = f()
        p.wg.Done()
    }()
    return p
}

func (p *Promise) Then(r func(string), e func(error)) {
    go func() {
        p.wg.Wait()
        if p.err != nil {
            e(p.err)
            return
        }
        r(p.res)
    }()
}

playground


I am also trying to implement javascript's promise :). It's a learning purpose project. In this implementation, I learn go's channel, select, goroutine. I think this small library meets your need.

p := New(func(resolve func(interface{}), reject func(error)) {
    resolve("sonla")
})

p.Then(func(data interface{}) interface{} {
    fmt.Printf("What I get is %v\n", data.(string))
    return nil
})

Await(p)

Welcome for contribution, if anyone has a better idea to implement promise in golang. Here is my repo


There's a paper called "From Events to Futures and Promises and back" by Martin Sulzmann (published in February 2016), which covers that topic. The abstract says:

Events based on channel communications and futures/promises are powerful but seemingly different concepts for concurrent programming. We show that one concept can be expressed in terms of the other with surprisingly little effort. Our results offer light-weight library based approaches to implement events and futures/promises. Empirical results show that our approach works well in practice.

According to the paper, futures look like this:

type Comp struct {
    value interface{}
    ok    bool
}

type Future chan Comp

func future(f func() (interface{}, bool)) Future {
    future := make(chan Comp)

    go func() {
        v, o := f()
        c := Comp{v, o}
        for {
            future <- c
        }
    }()

    return future
}

Whereas promises are implemented as follows:

type Promise struct {
    lock chan int
    ft   Future
    full bool
}

func promise() Promise {
    return Promise{make(chan int, 1), make(chan Comp), false}
}

func (pr Promise) future() Future {
    return pr.ft
}

Read up the paper for details, combinators and more.