1

I am new to Reason, currently trying to convert a personal project from js to reason. Mostly it has been easy so far apart from async stuff. I am not able to call my function recursively with delay. I have a function getPrice which returns a promise of int

type getPrice = unit => Js.Promise.t(int)

I want to make another function checkPrice, which checks the current price by given user price endlessly unless condition is met.

let rec checkPrice = (userPrice) =>
  Js.Promise.(
   getPrice()
    |> then_(
     (currentPrice) =>
       if (currentPrice >= userPrice) {
         resolve(currentPrice)
       } else {
         /* call this function with setTimeout */
         checkPrice(userPrice)
       }
   )
);

But I am getting type mismatch saying setTimeout should be of type unit

glennsl
  • 28,186
  • 12
  • 57
  • 75
user17472
  • 139
  • 9
  • Avoid the [`Promise` constructor antipattern](https://stackoverflow.com/q/23803743/1048572?What-is-the-promise-construction-antipattern-and-how-to-avoid-it)! Make a separate helper function that returns a promise for the timeout, then use promise chaining. – Bergi Nov 07 '17 at 09:30

1 Answers1

-1

The Js.Promise API is unfortunately absolutely terrible, mostly because the JS API is just plain unsound, but it's not very well thought out on the Reason side either. There might be some convenience fixes coming to Js.Promise, but hopefully the entire thing is replaced with a proper solution in the not too distant future.

In the here and now, however, you'll have to do something like this:

external toExn : Js.Promise.error => exn = "%identity";

let rec checkPrice = (userPrice) =>
  Js.Promise.(
    getPrice()
    |> then_(
     (currentPrice) =>
       if (currentPrice >= userPrice) {
         resolve(currentPrice)
       } else {
         Js.Promise.make((~resolve, ~reject) =>
           Js.Global.setTimeout(
             fun () =>
               checkPrice(userPrice)
               |> then_((v) => [@bs] resolve(v) |> Js.Promise.resolve)
               |> catch((e) => [@bs] reject(toExn(e)) |> Js.Promise.resolve)
               |> ignore,
             0
           ) |> ignore
         )
       }
   )
);
user17472
  • 139
  • 9
glennsl
  • 28,186
  • 12
  • 57
  • 75
  • ahh got it now, Thanks a lot for explaining Yes async (promises) are the only part cringeworthy right now, rest is an absolute delight Also wondering, can the type checker force me to write catch statements for promise ? Like it gives for non exhaustive pattern matches ? – user17472 Nov 07 '17 at 10:26
  • It can, and there's even a library wrapping promises that does so: https://github.com/wokalski/vow – glennsl Nov 07 '17 at 10:41