karet.xhr

1.0.0 • Public • Published

Karet XHR · Gitter GitHub stars

This library allows one to declare XMLHttpRequests, compose them, and observe them through Kefir properties. This makes it easy to implement many kinds of use cases ranging from just getting the response data to visualizing the progress of non-trivial compositions of ongoing upload and/or download requests and displaying potential errors.

Examples:

  • The Giphy CodeSandbox uses this library to do simple JSON GET requests.
  • The GitHub repository search CodeSandbox uses this library to do JSON GET requests and exercises much of the API of this library as an example.

npm version Build Status Code Coverage

Contents

Reference

The interface of this library consists of named exports. Typically one just imports the library as:

import * as XHR from 'karet.xhr'

Using this library, one declares observable XMLHttpRequests, composes them, and then observes the ongoing XHR using the accessors for the result, overall, download, and upload state.

Just give me the data!

If you just want to GET some JSON...

XHR.getJson(url | {url,[, ...options]}) ~> varies

XHR.getJson returns an observable that emits the full response after the XHR has succeeded. In case the XHR produces an error or times out, the XHR is emitted as an error event. See XHR.perform for the options.

Note that this function is provided for simplistic usages where one does not need the full composability and observability advantages of this library.

For example:

I.seq(
  XHR.getJson(`https://api.github.com/search/users?q=polytypic`),
  R.map(L.get(L.query('html_url'))),
  log
)

Declare

XHRs are declared by specifying all the parameters that affect the execution of an XHR to XHR.perform, which then returns an observable property that can be subscribed to in order to perform the declared XHR.

XHR.perform(url | {url[, ...options]}) ~> xhr

XHR.perform creates an observable property that represents the state of an ongoing XMLHttpRequest. The request is started once the property is subscribed to and is automatically aborted in case the property is fully unsubscribed from before it has ended. See also XHR.performWith and XHR.performJson.

Only the url parameter is required and can be passed as a string. Other parameters have their XHR default values:

Parameter Default Explanation
method 'GET' HTTP request method to use.
user null User name for authentication.
password null Password for authentication.
headers null An array of [header, value] pairs, a plain object of {header: value} properties, a Map, or a Headers object mapping headers to values.
overrideMimeType undefined If specified overrides the MIME type provided by the server.
body null A body of data to be sent.
responseType '' Specifies type of response data.
timeout 0 Number of milliseconds or 0 for infinite.
withCredentials false Whether cross-site Access-Control should use credentials.

In addition to a plain object, the argument to XHR.perform is allowed to be an observable property or contain observable properties, in which case the property created by XHR.perform performs the XHR with the latest argument values.

Note that typically one does not explicitly subscribe to the property, but one rather computes a desired view of the property, such as a view of the succeeded response, and combines that further into some more interesting property.

WARNING: Setting responseType to 'json' is not supported by IE 11. This library implements a workaround by calling JSON.parse on the returned data in case setting responseType to 'json' fails. In case the response does not parse, then XHR.response returns null.

XHR.performJson(url | {url[, ...options]}) ~> xhr

XHR.performJson is shorthand for XHR.performWith({responseType: 'json', headers: {'Content-Type': 'application/json'}}).

XHR.performWith(url | {...options}, url | {...options}) ~> xhr

XHR.performWith is a curried function that allows one to define a XHR.perform like function with default parameters. The defaults (first parameter) are merged with the overrides (second parameter). Headers are also merged. See XHR.perform for the parameters.

For example:

const get = XHR.performWith({responseType: 'json', timeout: 30*1000})
// ...
get(url)

Compose

Multiple XHRs can be composed together to appear and be treated simply as a single XHR.

Basic combinators

XHR.ap(xhrAtoB, xhrA) ~> xhrB

XHR.ap implements a static land compatible ap function for composing succeeding XHRs. The XHRs are performed sequentially. See also XHR.apParallel and XHR.apply.

XHR.apParallel(xhrAtoB, xhrA) ~> xhrB

XHR.apParallel implements a static land compatible ap function for composing succeeding XHRs. The XHRs are performed in parallel. See also XHR.ap and XHR.apply.

XHR.chain(A => xhrB, xhrA) ~> xhrB

XHR.chain implements a static land compatible chain function for composing succeeding XHRs.

XHR.map(A => B, xhrA) ~> xhrB

XHR.map implements a static land compatible map function for composing succeeding XHRs.

XHR.of(A) ~> xhrA

XHR.of implements a static land compatible of function for composing succeeding XHRs.

Additional combinators

XHR.apply((...As) => B, [...xhrAs]) ~> xhrB

XHR.apply maps the given XHRs through the given function. Unlike with XHR.ap, the XHRs are performed in parallel.

XHR.tap(A => ignored, xhrA) ~> xhrA

XHR.tap wraps the XHR so that the given action is called with the response after the XHR has succeeded. If the XHR does not succeed, the action will not be called.

Note that XHR.tap(action) is roughly equivalent to

XHR.map(response => {
  action(response)
  return response
})
XHR.template([ ... xhr ... ] | { ... xhr ... }) ~> xhr

XHR.template transforms a nested template of plain arrays and objects possibly containing XHRs into a XHR. The XHRs are performed in parallel.

Algebras

Static Land compatible algebras can be used with other Static Land compatible libraries such as Partial Lenses to perform more complex XHRs.

For example:

I.seq(
  XHR.performJson(`https://api.github.com/search/repositories?q=user:calmm-js&sort=stars`),
  XHR.map(
    L.collect([
      'items',
      L.limit(2, L.flat(L.when(R.has('description')))),
      L.pick({
        description: 'description',
        url: 'svn_url',
        issues: 'issues_url'
      })
    ])
  ),
  XHR.chain(
    L.traverse(
      XHR.Parallel,
      issues => I.seq(
        XHR.performJson(issues.replace(/{.*}$/, '')),
        XHR.map(
          L.collect(
            L.limit(3, L.flat(L.pick({title: 'title', url: 'html_url'})))
          )
        )
      ),
      [L.elems, 'issues']
    )
  ),
  XHR.result,
  log
)
XHR.IdentityParallel ~> applicative

XHR.IdentityParallel is a static land compatible applicative that manipulates XHRs like XHR.Parallel or plain data.

XHR.IdentitySucceeded ~> monad

XHR.IdentitySucceeded is a static land compatible monad that manipulates XHRs like XHR.Succeeded or plain data.

XHR.Parallel ~> applicative

XHR.Parallel is a static land compatible applicative that allows one to compose parallel XHR requests. In case any XHR fails, the composed XHR produces the first failed XHR. In case all XHRs succeed, the composed XHR produces the combined XHR as the result.

XHR.Succeeded ~> monad

XHR.Succeeded is a static land compatible monad comprised of the XHR.ap, XHR.chain, XHR.map, and XHR.of combinators that allows one to compose sequences of XHR requests that stop as soon as the first XHR does not succeed.

Observe

Ongoing XHRs can be observed both for their varying properties such as the number of bytes transferred and for their results.

Result

XHR.hasFailed(xhr) ~> boolean

XHR.hasFailed returns a possibly observable boolean property of an ongoing XHR that is true if its HTTP status does not indicate success or the download or the upload operation has errored or timed out.

XHR.hasSucceeded(xhr) ~> boolean

XHR.hasSucceeded returns a possibly observable boolean property of an ongoing XHR that is true if the XHR is done, its HTTP status indicates success, and neither download or upload has errored or timed out.

XHR.result(xhrA) ~> A

XHR.result returns the response of a succeeded XHR. Note that XHR.response allows one to obtain the response before the XHR is done and even when the XHR has (partially) failed.

Overall state

Progression
XHR.isStatusAvailable(xhr) ~> boolean

XHR.isStatusAvailable returns a possibly observable boolean property that tells whether HTTP status and response headers have been received and can be obtained. See also XHR.status, XHR.statusText, XHR.allResponseHeaders, and XHR.responseHeader.

XHR.isDone(xhr) ~> boolean

XHR.isDone returns a possibly observable boolean property that tells whether the XHR operation is complete (whether success or failure). See also XHR.hasSucceeded.

XHR.isProgressing(xhr) ~> boolean

XHR.isProgressing returns a possibly observable boolean property that tells whether the XHR operation has started, but has not yet ended.

End state
XHR.hasErrored(xhr) ~> boolean

XHR.hasErrored returns a possibly observable boolean property of an ongoing XHR that is true when either download or upload has errored.

XHR.hasTimedOut(xhr) ~> boolean

XHR.hasTimedOut returns a possibly observable boolean property of an ongoing XHR that is true when either download or upload has timed out.

Errors on failure
XHR.errors(xhr) ~> [...exceptions]

XHR.errors returns a possibly observable array of errors from download and upload. The array will contain 0 to 2 errors.

Request status
XHR.status(xhr) ~> number

XHR.status returns a possibly observable property that emits the status after the HTTP status has been received. When called on a non-observable XHR, readyState must be 2 or an Error will be thrown.

XHR.statusIsHttpSuccess(xhr) ~> boolean

XHR.statusIsHttpSuccess(xhr) is shorthand for XHR.isHttpSuccess(XHR.status(xhr)). Note that HTTP status is usually received before the download and upload phases have completed. See also XHR.hasSucceeded, XHR.status and XHR.isHttpSuccess.

XHR.statusText(xhr) ~> string

XHR.statusText returns a possibly observable property of the statusText after the HTTP status has been received. When called on a non-observable XHR, readyState must be 2 or an Error will be thrown.

Data transfer
XHR.loaded(xhr) ~> number

XHR.loaded returns a possibly observable property of the sum of downloaded and uploaded bytes.

XHR.total(xhr) ~> number

XHR.loaded returns a possibly observable property of the sum of total download and total upload bytes.

Response headers
XHR.allResponseHeaders(xhr) ~> string

XHR.allResponseHeaders returns a possibly observable property that emits the value of getAllResponseHeaders() after the HTTP headers have been received. When called on a non-observable XHR, its readyState must be 2 or an Error will be thrown.

XHR.responseHeader(header, xhr) ~> string

XHR.responseHeader returns a possibly observable property that emits the value of getResponseHeader(header) for specified header after the HTTP headers have been received. When called on a non-observable XHR, its readyState must be 2 or an Error will be thrown.

Response data
XHR.response(xhr) ~> varies

XHR.response returns a possibly observable property that emits the response after the download operation of the XHR has completed. When called on a non-observable XHR, the download operation must be completed or an Error will be thrown. See also XHR.result, and XHR.responseText.

XHR.responseText(xhr) ~> string

XHR.responseText returns a possibly observable property of the responseText property of an ongoing XHR. XHR.responseText is for observing the received response data before the data has been completely received. See also XHR.response.

XHR.responseXML(xhr) ~> document

XHR.responseXML returns a possibly observable property of the responseXML property after the XHR has completed. When called on a non-observable XHR, the download operation must be completed or an Error will be thrown. See also XHR.response.

Response URL
XHR.responseURL(xhr) ~> string

XHR.responseURL returns a possibly observable property of the responseURL property after the HTTP headers have been received. When called on a non-observable XHR, its readyState must be 2 or an Error will be thrown.

Request parameters
XHR.responseType(xhr) ~> string

XHR.responseType returns a possibly observable property of the responseType of an ongoing XHR.

XHR.timeout(xhr) ~> number

XHR.timeout returns a possibly observable property of the timeout property of an ongoing XHR.

XHR.withCredentials(xhr) ~> boolean

XHR.withCredentials returns a possibly observable property of the withCredentials property of an ongoing XHR.

Ready state
XHR.readyState(xhr) ~> number

XHR.readyState returns a possibly observable property of the readyState of an ongoing XHR.

Download state

XHR.downError(xhr) ~> exception

XHR.downError returns a possibly observable property of the error property of an errored XHR.

XHR.downHasEnded(xhr) ~> boolean

XHR.downHasEnded returns a possibly observable boolean property that tells whether the download operation of an ongoing XHR has ended.

XHR.downHasErrored(xhr) ~> boolean

XHR.downHasErrored returns a possibly observable boolean property that tells whether the download operation of an ongoing XHR has errored.

XHR.downHasStarted(xhr) ~> boolean

XHR.downHasStarted returns a possibly observable boolean property that tells whether the download operation of an ongoing XHR has started.

XHR.downHasCompleted(xhr) ~> boolean

XHR.downHasCompleted returns a possibly observable boolean property that tells whether the download operation of an ongoing XHR has been completed successfully. Note that this does not take into account the HTTP response status, see XHR.status and XHR.isHttpSuccess.

XHR.downHasTimedOut(xhr) ~> boolean

XHR.downHasTimedOut returns a possibly observable boolean property that tells whether the download operation of an ongoing XHR has timed out.

XHR.downIsProgressing(xhr) ~> boolean

XHR.downIsProgressing returns a possibly observable boolean property that tells whether the download operation of an ongoing XHR is progressing.

XHR.downLoaded(xhr) ~> number

XHR.downLoaded returns a possibly observable property of the loaded property of an ongoing XHR.

XHR.downTotal(xhr) ~> number

XHR.downTotal returns a possibly observable property of the total property of an ongoing XHR.

Upload state

XHR.upError(xhr) ~> exception

XHR.upError returns a possibly observable property of the error property of an errored XHR.

XHR.upHasEnded(xhr) ~> boolean

XHR.upHasEnded returns a possibly observable boolean property that tells whether the upload operation of an ongoing XHR has ended.

XHR.upHasErrored(xhr) ~> boolean

XHR.upHasErrored returns a possibly observable boolean property that tells whether the upload operation of an ongoing XHR has errored.

XHR.upHasStarted(xhr) ~> boolean

XHR.upHasStarted returns a possibly observable boolean property that tells whether the upload operation of an ongoing XHR has started.

XHR.upHasCompleted(xhr) ~> boolean

XHR.upHasCompleted returns a possibly observable boolean property that tells whether the upload operation of an ongoing XHR has completed successfully. Note that this does not take into account the HTTP response status, see XHR.status and XHR.isHttpSuccess.

XHR.upHasTimedOut(xhr) ~> boolean

XHR.upHasTimedOut returns a possibly observable boolean property that tells whether the upload operation of an ongoing XHR has timed out.

XHR.upIsProgressing(xhr) ~> boolean

XHR.upIsProgressing returns a possibly observable boolean property that tells whether the upload operation of an ongoing XHR is progressing.

XHR.upLoaded(xhr) ~> number

XHR.upLoaded returns a possibly observable property of the loaded property of an ongoing XHR.

XHR.upTotal(xhr) ~> number

XHR.upTotal returns a possibly observable property of the total property of an ongoing XHR.

Auxiliary

XHR.isHttpSuccess(number) ~> boolean

XHR.isHttpSuccess returns a possibly observable property of whether the given numeric property is in the range 2xx of HTTP success codes. See also XHR.statusIsHttpSuccess.

XHR.isXHR(any) ~> boolean

XHR.isXHR returns a possibly observable boolean property that tells whether the given value is a XHR.

Package Sidebar

Install

npm i karet.xhr

Weekly Downloads

2

Version

1.0.0

License

MIT

Unpacked Size

128 kB

Total Files

9

Last publish

Collaborators

  • polytypic