Javascript FFI with callbacks with less code

I’m trying to FFI

The API is as follows:

    parser.parseString(data, function (err, result) {

When expanding this using as a reference, I get

exports._parseString = function (parser) {
  return function (data) {
    return function (onError, onSuccess) {
      parser.parseString(data, function (err, data) {
        if (err) {


      return function (cancelError, onCancelerError, onCancelerSuccess) {


parseString :: Parser -> String -> Aff Foreign
parseString p s = fromEffectFnAff $ _parseString p s

on the PureScript side.

Is there a way to achieve this with a whole lot less JS code, e.g.

exports._parseString = function(parser, input, cb) { parser.parseString(input, cb) }


I’ve just checked your linked docs and there is xml2js promised based API xml2js.parseStringPromise. In the linked article there is a solution for simple promise based FFI so please ignore my all my hacky responses and use promise based API + aff-promise directly.


Maybe a bit hacky way by using node promisify + aff-promise. I hope I typed this correctly this time:

const util = require('util');

exports.parseStringImpl = function(parser) {
  return function() {
    return util.promisify(function(s, c) { parser.parseString(s, c); });


import Control.Promise as Promise

foreign import parseStringImpl :: Parser -> Effect (String -> Promise ...)

parseString parser s = liftEffect (parseStringImpl parser) >>= \p -> Promise.toAff (p s)

Not tested so it is possibly a rubbish :wink:

Thanks for the aff-promise hint. Shortest JS code I could come up with:

exports._parseStringPromise =
  function(parser, data) { return parser.parseStringPromise(data) }
foreign import _parseStringPromise ::
  EffectFn2 Parser String (Promise Foreign)

parseString :: Parser -> String -> Aff Foreign
parseString p s = toAffE $ runEffectFn2 _parseStringPromise p s
1 Like

You can use arrow function to get rid of EffectFn2 and runEffectFn2. Not tested

exports._parseStringPromise =
  parser => data => () => parser.parseStringPromise(data)
foreign import _parseStringPromise ::
  Parser -> String -> Effect (Promise Foreign)

parseString :: Parser -> String -> Aff Foreign
parseString p s = toAffE $ parseStringPromise p s