RationalJS / future

A Js.Promise alternative for ReasonML
214 stars 15 forks source link

Feature Request: When tap is not enough: execute #41

Closed seprich closed 4 years ago

seprich commented 4 years ago

The inferred signature of tap (and its relatives tapOk, tapError) are as follows:

let tap: (Future.t('a), 'a => unit) => Future.t('a);
let tapOk: (Future.t(Belt.Result.t('a, 'e)), 'a => 'z) => Future.t(Belt.Result.t('a, 'e));
let tapError: (Future.t(Belt.Result.t('a, 'e)), 'e => 'z) => Future.t(Belt.Result.t('a, 'e));

These functions do have the limitation that the side-effect function signature 'e => unit does not allow any async operations such as committing or rollbacking RDB transactions ; such operations would require 'a => Future.t(unit) type of signatures. In other words the execution chain should wait for the side-effect to become ready before continuing. Therefore I would propose the following additions to this library:

let execute: (Future.t('a), 'a => Future.t(unit)) => Future.t('a)
let executeOk: (Future.t(Belt.Result.t('a, 'e)), 'a => Future.t(Belt.Result.t(unit, 'e))) => Future.t(Belt.Result.t('a, 'e));
let executeError: (Future.t(Belt.Result.t('a, 'e)), 'e => Future.t(Belt.Result.t(unit, 'e))) => Future.t(Belt.Result.t('a, 'e));

These variants would execute the side effect function before continuing. In the basic case of execute the given function doesn't contribute any values to the chain - return value matches the 1st parameter exactly. For executeOk and executeError I am proposing a bit more complicated behavior: