supreme-ajax
Immutable-style AJAX library for the browser

Principles
- Immutable API
- Promise-based
- Throws meaningful errors
- Understands Content-Type
- Decodes JSON responses by default
- Works on modern browsers
- No external dependencies
- See polyfills for a list of polyfills you might need for older browsers
- Fully tested
Installation
Install via npm or yarn:
npm install supreme-ajax
yarn add supreme-ajax
Import in a project:
import request from 'supreme-ajax';
const request = require('supreme-ajax');
Usage
See these basic examples or the full API below.
request
.get('https://example.com')
.query({ foo: 'bar' })
.send()
.then(response => {
console.log(response.body);
})
.catch(error => {
console.error(error.response.status);
})
request
.post('https://example.com/accounts')
.body('raw data')
.send()
request
.post('https://example.com/accounts')
.json({ foo: 'bar' })
.send()
request
.post('https://example.com/accounts')
.urlencoded({ foo: 'bar' })
.send()
request
.baseUrl('https://example.com')
.get('/accounts')
.send()
request
.get('https://example.com')
.headers({
'X-Random': 1
})
.header('x-another', 'test')
.unsetHeader('x-another')
.send()
request
.get('https://example.com')
.timeout(2000)
.send()
request
.get('https://example.com/accounts.json')
.send()
.then(response => {
console.log(response.data);
})
request
.polyfills({ Promise: require('bluebird') })
.get('https://example.com')
.send()
Extending
Each method of ImmutableAjaxRequest
returns a new instance of ImmutableAjaxRequest
. This is demonstrated in the example below.
The example uses toObject
which returns a copy of all configuration of that specific instance at that moment in time.
const req1 = request
.get('https://example.com')
.query({ foo: 'bar' });
const req2 = req1.query({ something: 'different' });
console.log(req2 === req1);
console.log(req1.toObject().query);
console.log(req2.toObject().query);
Practical example of how to create a base request with some defaults and later utilize it for requests:
const api = request
.baseUrl('https://example.com/api/v1')
.headers({
'X-API-KEY': 'secret123'
});
api.get('/accounts').send();
api.post('/accounts').body(data).send();
Inspect request config
Use the API methods toObject
, config
or debug
to inspect the configuration of an ImmutableAjaxRequest
instance.
const req = request.get('https://example.com');
console.log(req.toObject().url);
API
The following methods are available.
get
.get(url)
Where url
is a string. Shorthand for request.method('get').url(url)
.
post
.post(url)
Where url
is a string. Shorthand for request.method('post').url(url)
.
method
Sets the HTTP method.
.method(method)
Where method
is a string, e.g. 'get'
or 'GET'
.
url
Sets the full URL of the request. If a query-string is present, it will override any previously set query parameters.
.url(url)
Where url
is a string, e.g. 'https://example.com/accounts'
.
baseUrl
Sets the base URL to which all subsequent request URLs will be appended.
.baseUrl(url)
Where url
is a string, e.g. 'https://example.com'
.
Refer to URL
documentation to see how baseUrl
and url
behave. A few examples:
request.baseUrl('https://example.com').url('accounts')
request.baseUrl('https://example.com/').url('accounts')
request.baseUrl('https://example.com').url('/accounts')
request.baseUrl('https://example.com/').url('/accounts')
request.baseUrl('https://example.com/nested').url('accounts')
request.baseUrl('https://example.com/nested').url('/accounts')
request.baseUrl('https://example.com/nested/').url('accounts')
request.baseUrl('https://example.com/nested/foo').url('accounts')
query
Sets query parameters from an object. Overwrites existing query.
.query(object)
Where object
is key-value object of query parameters to set (will be encoded using URLSearchParams#toString
), or a valid query string.
Sets request headers from an object. Overwrites existing headers.
.headers(object)
Where object
is key-value object of headers to set.
Example:
const req = request.headers({ 'x-example': 'foo' });
console.log(req.toObject().headers)
const req2 = req.headers({ 'x-token': 'secret123' });
console.log(req2.toObject().headers)
Sets request headers from an object. Only overwrites headers present in the given object.
.amendHeaders(object)
Where object
is key-value object of headers to set.
Example:
const req = request.headers({ 'x-example': 'foo' }).amendHeaders({ 'x-token': 'secret123' });
console.log(req.toObject().headers)
Adds or updates a header value.
.header(key, value)
Where key
is a string and value
is a string.
Example:
const req = request.header('x-example', 'foo').header('x-token', 'secret123');
console.log(req.toObject().headers)
Removes a header from the request.
.unsetHeader(name)
Where name
is a string.
Example:
const req = request.headers({ 'x-example': 'foo', 'x-token': 'secret123' }).unsetHeader('x-example');
console.log(req.toObject().headers)
body
Set the body of the request.
.body(data)
Where data
is a string.
See also json
and urlencoded
.
json
Sets a JSON-encoded body and sets the Content-Type
header to 'application/json'
.
.json(value)
Where value
is mixed.
Shorthand for request.header('Content-Type', 'application/json').body(JSON.stringify(value))
.
urlencoded
Sets a JSON-encoded body and sets the Content-Type
header to 'application/urlencoded'
.
.urlencoded(value)
Where value
is mixed.
Shorthand for request.header('content-type', 'application/x-www-form-urlencoded').body(_valueUrlEncoded_)
.
timeout
Sets a timeout after which the request will be aborted and the Promise rejected.
.timeout(milliseconds)
Where milliseconds
is an integer.
See also unsetTimeout
.
unsetTimeout
Removes the timeout-value previously set with timeout
.
.unsetTimeout()
send
Dispatches the request and returns a Promise
.
.send([body])
Where the optional argument body
is a string. If it is set, it will be set as the request body. Also see sendJson
and sendUrlencoded
.
The Promise resolves with a response
object.
request
.get('https://example.com')
.then(response => {
console.log(response.headers);
console.log(response.body);
console.log(response.status);
})
.catch(error => {
console.log(error.message);
console.log(error.response);
})
A new Promise
is always returned, and the ImmutableAjaxRequest
is not mutated, so you can send the same request multiple times.
const req = request.get('https://example.com');
req.send().then(response => {
console.log('first response', response);
});
req.send().then(() => {
console.log('second response', response);
});
See polyfills
for switching away from global Promise
(e.g. bluebird).
sendUrlencoded
Short-hand for .urlencoded(data).send()
.
.sendUrlencoded(data)
sendJson
Short-hand for .json(data).send()
.
.sendJson(data)
setResponseTransformers
Sets a list of response transformers which are called when a response is received. By default the list contains one transformer which decodes JSON bodies based on the response Content-Type
header.
Using this method you can remove the default transformer:
.setResponseTransformers([])
If you need to add it back, just set it again:
request.setResponseTransformers([ request.jsonResponseTransformer ]);
Transformer functions are executed sequentially in the order they are in the list, and they receive response
as the only parameter. Whatever value they return is passed onto the next transformer and eventually back to the Promise-chain.
request.setResponseTransformers([
response => {
response.foobar = 'some extra information from elsewhere, for example';
return response;
}
]);
setAllowedStatusCode
By default any 2XX status code resolves the Promise and other status codes will reject it. This can be customized using setAllowedStatusCode
.
.setAllowedStatusCode(allowed)
Where allowed
is an integer, a RegExp
or a function.
polyfills
Override global dependencies which are used internally. Most useful for adding polyfills or a custom Promise-implementation.
.polyfills(polyfills)
Where polyfills
is an object. See example for the possible dependencies you can override:
request.polyfills({
Promise: window.Promise,
URLSearchParams: window.URLSearchParams
})
Links to polyfills for older browsers if you need to support them (these automatically patch window.Promise
and window.URLSearchParams
; no need to use request.polyfills
):
toObject
Returns the request configuration as an object.
.toObject()
.config()
.debug()
Example:
const req = request.baseUrl('http://example.com').get('/info').header('X-Random', 'foo')
const config = req.toObject();
Development
Tests
For testing during development, the following command starts a web server which servers a web-based mocha runner:
$ yarn build
$ yarn mocha
Test server is running!
Open http://localhost:8080/ in your browser
Run full test suite, which runs the same mocha tests in all browsers via karma, among other things:
yarn test