promise

package module
v0.0.0-...-9164cf1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 11, 2015 License: MIT Imports: 3 Imported by: 3

README

promise Documentation

Package promise provides support for returning Promises in gopherjs. The simplest usage is to use the Promisify() function to convert a (potentially-blocking) function call into a promise. This allows easily converting a typical synchronous (idiomatic) Go API into a promise-based (idiomatic) JS api.

For example:

func main() {
  js.Global.Set("whoami", Promisify(whoami))
  // or as part of a structed object:
  js.Global.Set("api", map[string]interface{}{
    "whoami": Promisify(whoami),
  })
}
// This is a blocking function -- it doesn't return until the XHR
// completes or fails.
func whoami() (User, error) {
  if resp, err := http.Get("/api/whoami"); err != nil {
    return nil, err
  }
  return parseUserJson(resp)
}

Promisify allows JS to call the underlying function via reflection and automatically detects an 'error' return type, using the following rules, in order:

  • If the function panics, the promise is rejected with the panic value.

  • If the last return is of type 'error', then the promise is rejected if the returned error is non-nil.

  • The promise is resolved with the remaining return values, according to how many there are:

    0:  resolved with nil
    1:  resolved with that value
    2+: resolved with a slice of the values
    

If you want to manage the promise directly, use Promise:

func whoamiPromise() *js.Object {
  var p promise.Promise
  go func() {
  	if user, err := whoami(); err == nil {
  		p.Resolve(user)
  	} else {
  		p.Reject(err)
  	}
  }
  return p.Js()
}

Documentation

Overview

Package promise provides support for returning Promises in gopherjs.

The simplest usage is to use the Promisify() function to convert a (potentially-blocking) function call into a promise. This allows easily converting a typical synchronous (idiomatic) Go API into a promise-based (idiomatic) JS api.

For example:

func main() {
  js.Global.Set("whoami", promise.Promisify(whoami))

  // or as part of a structed object:
  js.Global.Set("api", map[string]interface{}{
    "whoami": promise.Promisify(whoami),
  })
}

// This is a blocking function -- it doesn't return until the XHR
// completes or fails.
func whoami() (User, error) {
  if resp, err := http.Get("/api/whoami"); err != nil {
    return nil, err
  }
  return parseUserJson(resp)
}

Promisify allows JS to call the underlying function via reflection and automatically detects an 'error' return type, using the following rules, in order:

  • If the function panics, the promise is rejected with the panic value.
  • If the last return is of type 'error', then the promise is rejected if the returned error is non-nil.
  • The promise is resolved with the remaining return values, according to how many there are: 0: resolved with nil 1: resolved with that value 2+: resolved with a slice of the values

If you want to manage the promise directly, use Promise:

func whoamiPromise() *js.Object {
  var p promise.Promise
  go func() {
  	if user, err := whoami(); err == nil {
  		p.Resolve(user)
  	} else {
  		p.Reject(err)
  	}
  }
  return p.Js()
}

Known Issues

This package still has some rough edges:

  • Does not adopt promise state when a promise is returned from a handler. E.g.: func Op1() Promise {...} func Op2() Promise {...} // Fails because when Op2 returns a promise, log is immediately called // instead of waiting for the Op2 promise to be fulfilled. Op1().Then(Op2, nil).Then(log, nil) To fix this, we need to be able to inspect the result of the success function and determine if it's a Promise (has a .then method), and if so we need to trigger downstream promises off of that instead of directly passing the result to the downstream promises.
  • Does not do JS object type detection on .then() args. The promises spec suggests we should handle arbitrary arguments. E.g: somePromise.then(function(){...}, 123) should be equivalent to somePromise.then(function(){...})
  • Promisify() doesn't not auto-convert JS to strongly-typed Go types. E.g.: type Foo string func something(f Foo) {...} cannot be called from JS as: something("asdf") Instead, something must have signature: func something(f string) { ... }

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Promisify

func Promisify(fn interface{}) interface{}

Promisify takes any Go function and converts it to a function that runs asynchronously and returns a Promise.

Note: Currently this does not convert javascript types to Go types even if they are structurally equivalent. It therefore works only with plain data types or values explicitly created by Go code (passed back to java).

Types

type Callback

type Callback func(value interface{}) interface{}

Callbacks are provided to promises and called when the promise is fulfilled (with the fulfilled value) or rejected (with the error). The return of the callback is passed to dependencies.

type Promise

type Promise struct {
	// contains filtered or unexported fields
}

Promise represents most of an implementation of the JS Promise/A+ spec (https://promisesaplus.com/).

Typical usage is:

func ExportedToJavascript(arg1 string, arg2 int, ...) *Promise {
  var p Promise
  go func() {
    result, err := computeResult(arg1, arg2, ...)
    if err == nil {
      p.Resolve(result)
    } else {
      p.Reject(err)
    }
  }()
  return p.Js()
}

This structure can be automatically implemented by Promisify(...), for example:

Promisify(computeResult)

func (*Promise) Js

func (p *Promise) Js() *js.Object

Js creates a JS wrapper object for this promise that includes the 'then' method required by the Promises/A+ spec.

func (*Promise) Reject

func (p *Promise) Reject(err interface{}) interface{}

Reject this promise with the specified errror. Either Resolve or Reject may be called at most once on a promise instance.

func (*Promise) Resolve

func (p *Promise) Resolve(value interface{}) interface{}

Resolve this promise with the provided value. Either Resolve or Reject may be called at most once on a promise instance.

func (*Promise) Then

func (p *Promise) Then(success, failure Callback) *Promise

Then registers success and failure to be called if the promise is fulfilled or rejected respectively. It returns a new promise that will be resolved or rejected with the result of the success or failure callbacks.

Note that if success or failure return a promise, the promise itself is passed along as the value rather than adopting the returned promise's state.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL