How do I initialize an instance asynchronously in Reason?


I’m working on a google extension which is a dictionary lookup app.

And the raw data(let’s say it’s a raw json) has to be requested online.
The example code is below.

let dict: Js.Dict.t(string) = Js.Dict.empty();

let lookup = (key: string): string => {
	Js.Dict.get(dict, key)

Api.getDictionary() /* type is Js.Promise.t(string) */
	|> Js.Promise.then_(tranferToJsDict) /* type is Js.Promise.t(Js.Dict.t(string)) */

I fetch the data somewhere and decode to data structure I prefer.
There is another function named lookup which retrieves the key(parameter)
And it would use dict for looking up.
However, I have no idea how to initialize dict via api promise since we can not mutate the global variable in reasonml.

I guess I need another pattern for this usage.
Any thought?


Mutation is possible via ref

let dict: ref(Js.Dict.t(string)) = ref(Js.Dict.empty());

let transferToJsDict = (result) => {
  dict :=result;

If you’re using React, then you can also store and update it in a state variable with React.useState.


The ref solution with Js.Dict.t is probably the easiest to begin with, but you can also use a mutable Hashmap if there are frequent updates: If your values are strings, you can directly use HashMapString.

If you want to put values into window and access them in a type-safe manner, then this approach can be useful:

module JsGlobals = {
  type t;
  [@bs.val] external t: t = "window";
  external setDict: (t, MyDict.t) => unit = "myDict"
  external getDict: t => MyDict.t = "myDict";

let g = JsGlobals.t;
JsGlobals.setDict(g, MyDict.make());

This will result in the following JS:

var g = window;
// (say MyDict.make() returns a string)
g.myDict = "";