heya-io
Version:
Intelligent I/O for browsers and Node.
291 lines (224 loc) • 10.4 kB
Markdown
# `io`
[![Build status][travis-image]][travis-url]
[![NPM version][npm-image]][npm-url]
[![Greenkeeper][greenkeeper-image]][greenkeeper-url]
[![Dependencies][deps-image]][deps-url]
[![devDependencies][dev-deps-image]][dev-deps-url]
A minimal, yet flexible I/O for browser and Node with promises. A thin wrapper on top of [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest),
and [fetch()](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API), with numerous callbacks to simplify and automate all aspects of I/O especially using [JSON](http://www.json.org/) as an envelope,
including to add more transports, and I/O orchestration plugin services.
It can run on Node using a specialized transport: [heya-io-node](https://github.com/heya/io-node). It greatly simplifies I/O on Node by leveraging enhanced features of `heya-io` in the server environment.
The following services are included:
* `io.cache` — a transparent application-level cache (supports [sessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) and
[localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) out of the box).
* `io.bundle` — a transparent service to bundle requests into one package passing it to a server, and unbundling a result.
It requires a simple server counterpart. [heya-bundler](https://github.com/heya/bundler) is a reference implementation for node.js/express.js.
* `io.track` — a simple plugin to track I/O requests to eliminate duplicates, register an interest without initiating I/O requests, and much more.
* `io.mock` — a way to mock I/O requests without writing a special server courtesy of [Mike Wilcox](https://github.com/clubajax). Very useful for rapid prototyping and writing tests.
* `io.bust` — a simple plugin to generate a randomized query value to bust browser's cache.
* `io.retry` — a plugin to retry unreliable services or watch changes over time.
The following additional transports are provided:
* `io.fetch()` — replaces `XHR` with `fetch()`-based transport.
* `io.jsonp()` — [JSON-P](http://json-p.org/) requests.
* `io.load()` — generates `<script>` tags to include JavaScript files.
Utilities:
* `url()` — uses ES6 tagged literals to form properly sanitized URLs.
As is `heya-io` uses the standard [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
Given that not all browsers provide it, `heya-io` can be used with any then-able, but it was especially tested with implementations provided by [heya-async](https://github.com/heya/async):
[FastDeferred](https://github.com/heya/async/wiki/async.FastDeferred) and [Deferred](https://github.com/heya/async/wiki/async.Deferred).
With those modules an extended API is supported: I/O progress reports, and cancellation of I/O requests.
# Examples
Plain vanilla GET:
```js
heya.io.get('http://example.com/hello').then(function (value) {
console.log(value);
});
heya.io.get('/hello', {to: 'world', times: 5}).then(function (value) {
// GET /hello?to=world×=5
console.log(value);
});
```
POST a form (can include files or any other form elements):
```js
var formElement = document.querySelector('form');
heya.io.post('/form', new FormData(formElement));
```
Some other verbs ([REST](https://en.wikipedia.org/wiki/Representational_state_transfer) example):
```js
function done() { console.log('done'); }
heya.io.post('/things', {name: 'Bob', age: 42}).then(done);
heya.io.put('/things/5', {name: 'Alice', age: 33}).then(done);
heya.io.patch('/things/7', {age: 14}).then(done);
heya.io.remove('/things/3').then(done);
```
Modern browsers:
```js
const doIO = async query => {
const result = await heya.io.get('/hello', {q: query});
await heya.io.post('/things', {name: 'Bob', age: 42, friendly: result});
}
```
Other transports:
```js
// let's make a JSON-P call:
heya.io.jsonp('/planets', {query: 'name'}).then(function (values) {
// GET /planets?query=name
console.log('We have ' + values.length + ' planets:', values);
});
```
Mock:
```js
// set up a mock handler
heya.io.mock('/a*', function (options, prep) {
console.log('Got call: ' + options.method + ' ' + prep.url);
return 42;
});
// let's make a call
heya.io.get('/a/x').then(function (value) {
console.log(value); // 42
});
// set up a redirect /b => /a/b
heya.io.mock('/b', function (options) {
return heya.io.get('/a/b', options.query || options.data || null);
});
// let's make another call
heya.io.get('/b', {q: 1}).then(function (value) {
console.log(value); // 42
});
```
Using `url` template to sanitize URLs (ES6):
```js
const client = 'Bob & Jordan & Co';
heya.io.get(url`/api/${client}/details`).then(function (value) {
// GET /api/Bob%20%26%20Jordan%20%26%20Co/details
console.log(value);
});
```
See more examples in the cookbooks:
* [Cookbook: main](https://github.com/heya/io/wiki/Cookbook:-main)
* Services:
* [Cookbook: bundle](https://github.com/heya/io/wiki/Cookbook:-bundle)
* [Cookbook: cache](https://github.com/heya/io/wiki/Cookbook:-cache)
* [Cookbook: mock](https://github.com/heya/io/wiki/Cookbook:-mock)
* [Cookbook: track](https://github.com/heya/io/wiki/Cookbook:-track)
* Transports:
* [Cookbook: jsonp](https://github.com/heya/io/wiki/Cookbook:-jsonp)
* [Cookbook: load](https://github.com/heya/io/wiki/Cookbook:-load)
* [Cookbook: fetch](https://github.com/heya/io/wiki/Cookbook:-fetch)
# How to install
With npm:
```txt
npm install --save heya-io
```
With bower:
```txt
bower install --save heya-io
```
# How to use
`heya-io` can be installed with `npm` or `bower` with files available from `node_modules/` or `bower_components/`. By default, it uses AMD:
```js
define(['heya-io'], function (io) {
io.get('/hello').then(function (value) {
console.log(value);
});
});
```
But it can be loaded with `<script>` tag from `dist/`:
```html
<script src='node_modules/heya-io/dist/io.js'></script>
```
And used with globals like in examples above:
```js
heya.io.get('/hello').then(function (value) {
console.log(value);
});
```
To support browsers without the standard `Promise`, you may want to use [heya-async](https://github.com/heya/async).
AMD:
```js
define(['heya-io', 'heya-async/FastDeferred'], function (io, Deferred) {
// instrument
io.Deferred = Deferred;
// now we are ready for all browsers
io.get('/hello').then(function (value) {
console.log(value);
});
});
```
Globals:
```html
<script src='node_modules/heya-io/dist/io.js'></script>
<script src='node_modules/heya-async/dist/Micro.js'></script>
<script src='node_modules/heya-async/dist/FastDeferred.js'></script>
```
```js
// instrument
heya.io.Deferred = heya.async.FastDeferred;
// now we are ready for all browsers
heya.io.get('/hello').then(function (value) {
console.log(value);
});
```
See [How to include](https://github.com/heya/io/wiki/How-to-include) for more details.
# Documentation
All documentation can be found in [project's wiki](https://github.com/heya/io/wiki).
# Working on this project
In order to run tests in a browser of your choice, so you can debug interactively, start the test server:
```bash
npm start
```
Then open this URL in a browser: http://localhost:3000/tests/tests.html It will show a blank screen, but the output will appear in the console of your developer tools.
The server runs indefinitely, and can be stopped by Ctrl+C.
# Versions
- 1.9.3 *Refreshed dev dependencies.*
- 1.9.2 *Switched `retry` to the UMD loader so it can be used in Node directly.*
- 1.9.1 *Minor improvements of the `retry` service.*
- 1.9.0 *Bugfixes and refactoring in the `retry` service.*
- 1.8.0 *Added `retry` service. Thx [Jason Vanderslice](https://github.com/jasonvanderslice)!*
- 1.7.1 *Refreshed dev dependencies.*
- 1.7.0 *Added `AbortRequest`.*
- 1.6.2 *Added separate `options.onDownloadProgress()` and `options.onUploadProgress()`.*
- 1.6.1 *Added extra properties to progress data.*
- 1.6.0 *Added `options.onProgress()` and tests on Firefox Puppeteer.*
- 1.5.0 *Added cache removal by a function.*
- 1.4.2 *Added `ignoreBadStatus` flag when `returnXHR`.*
- 1.4.1 *Technical release. No changes.*
- 1.4.0 *Added mocks by regular expressions and matcher functions.*
- 1.3.0 *Added cache removal by regular expressions and wildcards.*
- 1.2.6 *Bugfixes: `getHeaders()` behaves like on Node, empty object queries are supported.*
- 1.2.5 *Exposed `io.getData(xhr)` and `io.getHeaders(xhr)`.*
- 1.2.4 *Relaxed cache's detection of Result().*
- 1.2.3 *Regenerated dist.*
- 1.2.2 *Moved tests to Puppeteer, bugfixes, improved docs.*
- 1.2.1 *Added Ignore type for data processors, bugfixes.*
- 1.2.0 *Clarified DELETE, added more well-known types.*
- 1.1.7 *Refreshed dependencies.*
- 1.1.6 *Bugfix: `processFailure` could be skipped.*
- 1.1.5 *Bugfix: MIME processors. Thx [Bryan Pease](https://github.com/Akeron972)!*
- 1.1.4 *Added custom data and MIME processors.*
- 1.1.3 *Formalized requests and responses with no bodies.*
- 1.1.2 *Minor fixes for non-browser environments. New alias and verb.*
- 1.1.1 *Added `url` tagged literals (an ES6 feature).*
- 1.1.0 *Added fetch() as an alternative default transport.*
- 1.0.9 *Correcting typos in README. New version of a test server.*
- 1.0.8 *Add a helper for busting browser cache.*
- 1.0.7 *Regenerated dist.*
- 1.0.6 *Added a helper to extract data from XHR in case of errors.*
- 1.0.5 *XHR can be reinstated from a JSON object, not just a string.*
- 1.0.4 *Regenerated dist.*
- 1.0.3 *Bugfix: cache XHR object directly.*
- 1.0.2 *Fixed formatting errors in README.*
- 1.0.1 *Improved documentation.*
- 1.0.0 *The initial public release as heya-io. Sunset of heya-request. Move from bitbucket.*
# License
BSD or AFL — your choice.
[npm-image]: https://img.shields.io/npm/v/heya-io.svg
[npm-url]: https://npmjs.org/package/heya-io
[deps-image]: https://img.shields.io/david/heya/io.svg
[deps-url]: https://david-dm.org/heya/io
[dev-deps-image]: https://img.shields.io/david/dev/heya/io.svg
[dev-deps-url]: https://david-dm.org/heya/io?type=dev
[travis-image]: https://img.shields.io/travis/heya/io.svg
[travis-url]: https://travis-ci.org/heya/io
[greenkeeper-image]: https://badges.greenkeeper.io/heya/io.svg
[greenkeeper-url]: https://greenkeeper.io/