Uninterpreted delimitersj

bsb

#1

I tried to run the following code I came across in the forums while searching for let Await.

module Await = {
  let let_ = (promise, continuation) =>
    promise
    |> Js.Promise.then_(value => continuation(value) |> Js.Promise.resolve);
};

let _ = {
  let%Await x = Js.Promise.resolve("from promise");
  let%Await y = Js.Promise.resolve(123);

  Js.log({j|y = $y|j});
  Js.log({j|x = $x|j});
};

I am getting this error:

>>>> Start compiling
[1/2] Building src/index.mlast

  We've found a bug for you!
  /Users/prisc_000/working/AMP/haiti-guide-cra2/src/index.re 42:12-23

  40 ┆   let%Await y = Js.Promise.resolve(123);
  41 ┆
  42 ┆   Js.log({j|y = $y|j});
  43 ┆   Js.log({j|x = $x|j});
  44 ┆ };

  Uninterpreted delimitersj

ninja: error: rebuilding 'build.ninja': subcommand failed
>>>> Finish compiling(exit: 1)

I cant figure out how I need to format the Js.log. Any ideas would be appreciated. Thank you.


#2

Wow, never seen that one before. Just checking though–you are using Jared Forsyth’s let-anything PPX, correct? This code is meant to be used with that.

If nothing else works, you could try Js.log2("y =", y);


#3

In fact, i had get_in_ppx and not let_in_ppx. Works now. Thank you @yawaramin.

While I have you. How does one go about using the return value from let anything?

If i do this, to follow with that example:

module Await = {
    let let_ = (promise, continuation) =>
      promise
      |> Js.Promise.then_(value => continuation(value) |> Js.Promise.resolve);
  };
  // let%Await user = Js.Promise.resolve(User.getUser());
  // // Js.log(user);
  // Js.log2("AwaitUser: ", user)
  let _ = {
    let%Await x = Js.Promise.resolve("from promise");
    let%Await y = Js.Promise.resolve(123);
    let%Await user = Js.Promise.resolve(User.getUser());
    Js.log({j|y = $y|j});
    Js.log({j|x = $x|j});
    Js.log(y);
    Js.log(x);
    Js.log(user);
  };

I get this output in the console:

 y = 123 index.bs.js:65
x = from promise index.bs.js:66
123 index.bs.js:67
from promise index.bs.js:68
Array(3) [ "idkjs", "aarmand.inbox@gmail.com", "+15555555555" ]
index.bs.js:69

If i do,

let user = {
  let%Await user = Js.Promise.resolve(User.getUser());
  Js.log2("AWAITING_USER_INSIDE: ", user);
  user;
};
Js.log2("AWAITING_USER: ", Js.Promise.resolve(user));
Js.log2("AWAITING_USER: ", user);


let user = () => {
  let%Await user = Js.Promise.resolve(User.getUser());
  Js.log2("AWAITING_USER_INSIDE_WITH_FUNCTION: ", user); //this never logs
  user;
};
Js.log2("AWAITING_USER_FUNCTION: ", Js.Promise.resolve(user));

I get:

 AWAITING_USER:  
Promise { <state>: "pending" }
index.bs.js:43
 AWAITING_USER:  
Promise { <state>: "pending" }
AWAITING_USER_FUNCTION:  
Promise { "fulfilled" }
​
<state>: "fulfilled"
​
<value>: function user$1()​
<prototype>: PromiseProto { … }
index.bs.js:52

AWAITING_USER_INSIDE:  
Array(3) [ "idkjs", "aarmand.inbox@gmail.com", "+15555555555" ]
index.bs.js:39

What is going on here?

Also, I would love some links to resources for Promise error handling and promises in general, i feel like i keep running into the same mistakes. Thanks, brother.


#4

Here is concrete example demonstrating my question about how to use a response value.

I have this function which works:

I commented out an attempt with let%Await. How would I get that to work in this case?

let make = () => {
  let (state, dispatch) = React.useReducer(reducer, {response: None});
  React.useEffect(() => {
    // let user = Js.Promise.resolve(user)
    // let%Await user = Js.Promise.resolve(User.getUser());
    // user;
    // Js.log2("USER_PROFILE",user)
    // dispatch(SetResponse(user))
    User.getUser()
    |> Js.Promise.then_(user => {
         //  Js.log2("USER_PROFILE",user)
         dispatch(SetResponse(user));
         Js.Promise.resolve([]);
       })
    |> Js.Promise.catch(err => {
         Js.log(err);
         let errMsg = "An error occurred: " ++ Js.String.make(err);
         Js.log(errMsg);
         Js.Promise.resolve([errMsg]);
       });
    //  |> ignore
    None; // so the effect will only run once, on mount. Also, the second arg to useEffect is the initial state so we are passing None option as initial state.
  });

#5

If User.getUser() returns a promise of user, then Js.Promise.resolve(User.getUser()) returns a promise of a promise of a user. That’s why you’re getting weird output. If you get rid of the extra resolve, it should be fine.

I tried to write a code sample using let-anything to handle the promise and errors, but I actually couldn’t figure out how to do it. Let-anything might not actually be a great fit for JavaScript promises in the presence of promise rejection, I’m happy to be proven wrong though. For now I recommend sticking with the functions in Js.Promise.

Btw, if you want to run an effect hook only once, you should be using React.useEffect0, which passes in an empty array as the effect’s ‘dependency’ array. This ensures the effect is not dependent on anything and thus never re-runs. See the ‘Note’ in this section: https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects