Using webapi is a bit like writing DOM code with TypeScript strict enabled. If the spec says something can be any element, that’s the type you get. If the spec says something might be null, it will return an optional value. Code can’t assume document.createElement and event.currentTarget return the element you know they do; the value needs to be converted (or coerced) into image elements.
The library also doesn’t map onload or onerror, the more modern event listener style is all it makes available.
So, the first block:
open Webapi.Dom;
let processImage = url => {
Promise.make((resolve, reject) => {
// showing each step of the chain, this can be done more easily (see below)
let e = document->Document.createElement("img")
let maybeImg = HtmlImageElement.ofElement(e)
let img = Belt.Option.getUnsafe(maybeImg)
img->HtmlImageElement.setSrc(url)
img->HtmlImageElement.addLoadEventListener(event => resolve(. event))
img->HtmlImageElement.addErrorEventListener(error => reject(. error))
let body =
document
->Document.asHtmlDocument
->Belt.Option.flatMap(HtmlDocument.body)
->Belt.Option.getUnsafe
body->Element.appendChild(~child=img->HtmlImageElement.asNode)
body->Element.removeChild(~child=img->HtmlImageElement.asNode)->ignore
})
}
Note that Belt.Option.getUnsafe is not a great thing to have in production code but given the element was only just created, it’s fine (as the JS is).
The second becomes:
url
->processImage
->Promise.thenResolve(event => {
// similar to the above chain, but done all at once without interim variables
let img =
event
->Event.currentTarget
->EventTarget.unsafeAsElement
->HtmlImageElement.ofElement
->Belt.Option.getUnsafe
let width = img->HtmlImageElement.naturalWidth
let height = img->HtmlImageElement.naturalHeight
// ...
})
I normally wouldn’t use getUnsafe here, preferring a switch statement to unwrap the optional image properly, but it’ll do for this example.
Since I had already written this up for you I published it as an example in webapi. The generated JS shows, if you gloss over the runtime curry and belt management code, something not far from the original JS.