ReScript wrapper for XMLHttpRequest
Run the following in your console:
$ yarn add rescript-future rescript-request
Then add rescript-request
and rescript-future
to your bsconfig.json
's bs-dependencies
:
{
"bs-dependencies": [
+ "rescript-request",
+ "rescript-future
]
}
Request.make
performs a request and returns a Future.t
containing a result<response, error>
.
Request.make(~url="/api/health", ~responseType=Text, ())
->Future.get(Js.log)
// Ok({
// status: 200,
// ok: true,
// response: "{\"ok\":true}",
// })
Request.make(~url="/api/health", ~responseType=Text, ())
->Future.get(Js.log)
// Error(#NetworkError)
Request.make(~url="/api/health", ~responseType=Text, ~timeout=10, ())
->Future.get(Js.log)
// Error(#Timeout)
Request.make(~url="/api/health", ~responseType=Json, ())
->Future.get(Js.log)
// Ok({
// status: 200,
// ok: true,
// response: {"ok":true},
// })
type response = {"ok": bool}
Request.make(
~url="/api/health",
~responseType=(JsonAsAny: Request.responseType<response>),
()
)
->Future.get(Js.log)
// Ok({
// status: 200,
// ok: true,
// response: {"ok":true},
// })
url
: string,method
:#GET
(default),#POST
,#OPTIONS
,#PATCH
,#PUT
or#DELETE
responseType
:Text
: (default) response will bestring
ArrayBuffer
: response will beJs.TypedArray2.ArrayBuffer.t
Document
: response will beDom.document
Blob
: response will beRequest.blob
Json
: response will beJs.Json.t
JsonAsAny
: response will be any, use with(JsonAsAny: Request.responseType<yourType>)
body
: anyheaders
:Js.Dict
containing the headerswithCredentials
: boolonLoadStart
onProgress
timeout
: int
The response is a record containing:
status
:int
ok
:bool
response
: the decoded response, which is anoption
#NetworkRequestFailed
#Timeout
You can map the Request.error
types to your own:
type error =
| Empty
| NetworkError
| Timeout
let mapError = error => {
switch error {
| #NetworkRequestFailed => NetworkError
| #Timeout => Timeout
}
}
let emptyToError = ({Request.response: response}) => {
switch response {
| None => Error(Empty)
| Some(value) => Ok(value)
}
}
let requestApi = (~url, ~responseType) => {
Request.make(~url, ~responseType, ())
->Future.mapError(~propagateCancel=true, mapError)
->Future.mapResult(~propagateCancel=true, emptyToError)
}
Don't forget to use the
propagateCancel
option so that callingFuture.cancel
on therequestApi
return value aborts the request!