Uploaded by

Simple library for interop between Aff and JavaScript promises.

No typeclass instances etc are provided to use Promises directly - the intention is that your PureScript code uses Aff internally, and is only wrapped as a Promise to present an API for consumption in JavaScript code (and vice versa).

Exposing promises: Aff to Promise

The origin of this library was to solve the following problem: I want to write asynchronous code in Aff, but I need to expose this as an API to JavaScript in the form of a Promise.

Therefore the majority of code can be written to return an Aff, in this example using readTextFile from purescript-node-fs-aff:

getLinesAff :: forall eff. Aff (fs :: FS | eff) (Array String)
getLinesAff = do
  text <- readTextFile Encoding.UTF8 "data.txt"
  pure $ split (Pattern "\n") text

and this can be exposed as a function returning a promise:

import Control.Promise as Promise

getLines :: forall eff. Eff (fs :: FS | eff) (Promise (Array String))
getLines = Promise.fromAff getLinesAff

This function returns an Eff beause a promise is "already running". A JavaScript function consuming this API would just call getLines().then(...).

Consuming promises: Promise to Aff

The reverse problem occurs when wrapping a JS library that uses promises for asynchronous behaviour (Aff comes with a perfectly good function to deal with consuming libraries that use callbacks).

Consider the case of consuming the fetch API.

exports.fetchImpl = function (url) {
  return function() {
    return fetch(url);
foreign import data Response :: Type
foreign import fetchImpl :: String -> Eff (Promise Response)

Notice that the fetch(url) call is wrapped in a thunk and imported as an Eff, because otherwise the fetch operation would be initiated as a side-effect of a pure function - while fetch returns a promise, at the point the function returns the network request has already been initated.

The response can then be converted to an Aff and consumed easily:

import Control.Promise as Promise

fetch :: forall eff. String -> Aff (net :: NET | eff) String
fetch url = liftEff (fetchImpl url) >>= Promise.toAff

API documentation is available on Pursuit.