Promise nested inside an option is throwing error

Looks like a bug, but I am not sure. Somebody can shed some light on this.

Consider the below code. In the below code, a promise holds an option which again holds another promise. Now if I have to change the value in the inner most promise, then the natural way to do it is to write a then_ for first promise, a map on the option and a then_ on the inner most promise.

let opPromise: option<Js.Promise.t<int>> = 
    Some(Js.Promise.resolve(1))

let promiseOpPromise: Js.Promise.t<option<Js.Promise.t<int>>> = 
    Js.Promise.resolve(opPromise)

let _ = {
  // First promise
  Js.Promise.then_(d =>
    Js.Promise.resolve(
      // Option
      Belt.Option.map(
        d,
        // Inner most promise
        Js.Promise.then_(f => Js.Promise.resolve(f + 1)),
      ),
    )
  , promiseOpPromise)
}

This code compiles fine. But will throw the below error :point_down:t3: if you try to run it.

(node:18716) UnhandledPromiseRejectionWarning: TypeError: param.then is not a function

I am not sure why this is happening. Please advise.

I think this a know issue. Promise nested inside another Promise.

https://github.com/ryyppy/rescript-promise/blob/master/PROPOSAL.md#nested-promises-issue-trade-offs

In Rescript, type of Js.Promise.resolve(Js.Promise.resolve(1)) is inferred as Js.Promise.t<Js.Promise.t<int>>

but in JavaScript Promise.resolve(Promise.resolve(1)) evaluates to Promise.resolve(1) which is of type Js.Promise.t<int>

MDN

1 Like

@a-c-sreedhar-reddy Thanks for detailed explanation. I think the rescript has to capture that automatic flatmapping by js Promise. @Hongbo Can you please confirm if this is a bug?

Thank you @bikallem and @a-c-sreedhar-reddy. I created a work around for this well known issue for my use case here.

this is not a bug from the compiler’s point of view.
It is a known issue for the promise lib. You can work around it using a box, for example, #Box (promise), note it does not work with option since option is a primitive data type and it is unboxed for some reasons

Thanks @Hongbo. Yes, I came up with a similar solution using suggestions from @bikallem.
:point_right:t2: Solution