hajax
v0.0.6
Published
Highly available ajax solution
Downloads
171
Maintainers
Readme
HAjax
Browser-side high availability front-end request solution
Feature
- Easily handle Ajax cached data, front-end request concurrency
- Easy "debounce" and "throttle" operation
- Interceptor of request and response
- Request cancellation
- Failure retry
- Chained call of class Promise
- Automatically convert JSON type response data
Documents
Install
use npm:
$ npm install hajax
use script:
<script src="hx.min.js"></script>
Basic
Execute GET
request
import hx from 'hajax'
// Request a restful api for testing
hx.get('http://jsonplaceholder.typicode.com/users/1')
.then(function (response) {
// success handler
console.log(response);
})
.catch(function (error) {
// error handler
console.log(error);
})
Execute POST
request
// Request a restful api for testing
hx.post('/posturl')
.then(function (response) {
// success handler
console.log(response);
})
.catch(function (error) {
// error handler
console.log(error);
})
Execute concurrent requests: all
(blocking)
function getOne() {
return hx.get('/geturl1');
}
function getTwo() {
return hx.get('/geturl2');
}
hx.all([getOne(), getTwo()])
.then((function (responses) {
// The method here will be executed when all the requests in the all method are executed successfully.
// "responses" is an ordered array containing the data returned by the above two requests, arranged in the order of the parameters
}));
If you want to use this API and don't want to be blocked by a failed request, you can try the following
Execute concurrent requests: all
(non-blocking)
function getOne() {
return new Promise(function (resolve, reject) {
hx.get('/geturl1')
.then(function (resp) {
resolve(resp)
})
.catch(function () {
resolve()
})
})
}
function getTwo() {
return new Promise(function (resolve, reject) {
hx.get('/geturl2')
.then(function (resp) {
resolve(resp)
})
.catch(function () {
resolve()
})
})
}
hx.all([getOne(), getTwo()])
.then((function (responses) {
// Here, traversing the response parameters to determine whether the response is undefined, it means the request failed.
}));
Cache Config
Handle requests and data caching more easily with hajax
Compare common caching strategies with hajax caching strategies
Normal
working process:
- Determine if there is cached data
- Send a request if it does not exist, and get the response data and put it in the cache
- Subsequent requests to read cached data
Cache strategy:
After the first request is successful, subsequent requests will use the cache. In the same request concurrent scenario (generally caused by poor code writing), multiple identical requests will be sent at the same time; the expiration time is generally from Save data and start calculating
Disadvantage:
Inconvenient to use, the method needs to be encapsulated by itself, and the concurrent request is cache invalidation, which increases maintenance costs.
hajax:
working process:
- Determine if there is cached data
- Determine if the cache policy is met
- Send a request, if the cache policy is satisfied, put the obtained response data into the cache
- The next request that satisfies the cache policy determines whether the cache expires
- Read the cache directly if it has not expired, and regain the data refresh cache when it expires
Cache strategy:
After the first request is sent, the cache buffer is opened and the cache expiration time is calculated. All requests before the expiration time will be placed in the callback trigger of the request buffer, after the first request is completed. Time to distribute data to the callback buffer waiting for requests to be processed
Disadvantage:
By default, when the first request fails, all subsequent requests will fail. The solution here may be for discussion. You can add the retry retry mechanism by adding retryLimit
to the first request (my idea) Is to prepare an automatic retry switch, the number of retries is the current number of the same request)
How To Use
//Configuring the cache with "setStrategy"
//Generate a cache policy with "createStrategy"
hx.setStrategy(
hx.createStrategy('http://hajax.test/index.php', 4000, false)
)
//Send requests directly and cache data
hx.get('http://hajax.test/index.php').then(function (resp) {
console.log('success', resp)
}).catch(function (resp) {
console.log('failed', resp)
})
setTimeout(function () {
//Get cached data directly
hx.get('http://hajax.test/index.php').then(function (resp) {
console.log('success', resp)
}).catch(function (resp) {
console.log('failed', resp)
})
setTimeout(function () {
//Cache expired, re-requesting to get data
hx.get('http://hajax.test/index.php').then(function (resp) {
console.log('success', resp)
}).catch(function (resp) {
console.log('failed', resp)
})
}, 3000)
}, 3000)
hx.createStrategy(exp[, bufferTime[, autoRetry])
exp(必填):
- 确定的url: 在字符串匹配模式下,http://www.api.com 不等同于 www.api.com,这种缓存的匹配策略还有很多可以改善的地方,如果你有什么想法,随时可以告诉我
- 正则表达式
- '*'
bufferTime(默认:-1 即缓存在页面刷新后过期): 缓存时间; autoRetry(默认:true): 缓存模式下,失败是否自动重新请求策略,重试次数为:请求结束之前除主请求(实际发送出去的请求)以外的缓存请求的个数;
HAjax API
Custom requests can be made by passing the relevant configuration to a specific request
hx.request(config)
// Send a POST request using the "request" method
hx.request({
method: 'post',
url: '/url',
data: {
name: 'bennnis'
}
});
// Use the post method directly
hx.post('/url', {
name: 'bennnis'
});
Request method alias
In order to more conveniently call the corresponding request method, I provide the corresponding alias for all the request methods.
hx.request(config)
hx.get(url[, config])
hx.head(url[, config])
hx.options(url[, config])
hx.post(url[, data[, config])
hx.put(url[, data[, config])
hx.patch(url[, data[, config])
hx.delete(url[, data[, config])
Concurrent request method
Use a function to handle concurrent requests better
hx.all(requests: Array<Promise>)
hx.race(requests: Array<Promise>)
Create instance
You can create a new instance with a specific attribute to fit an unconventional situation that might appear in the system.
The new instance is identical to the default hx
instance.
hx.create([config])
//main.js
const hxDriver = hx.create({
baseURL: 'http://www.domain.org/api/v1/',
timeout: 1000,
headers: {'X-Custom-Header': 'foo'}
});
export default hxDriver
//app.js
import hxDriver from 'main'
hxDriver.request(config)
.then(function (resp) {
// handle success
})
.catch(function (err) {
// handle error
})
Request Config
Parameters other than url
are optional.
{
// `url`
// Request address (required): can be relative and absolute
public url: string
// `method`
// Request method
public method: string // default: 'get'
// `baseURL`
// Request address prefix. When 'url' is a relative path, baseURL is added to the final request address.
public baseURL: string // default: '/'
// `headers`
// Request headers
public headers: object // default: {'Content-Type': 'application/json'}
// `params`
// The final request to the parameters in the url, as an object type
// Will stitch the corresponding key-value to the back of the request url
public params: object
// `data`
// The data to be sent as the request body is only valid at "post"
public data: object
// `timeout`
// Timeout of request: in milliseconds, the request for timeout will be automatically terminated
public timeout: number
// `withCredentials`
// Whether to use a certificate similar to cookies, authorization headers or TLS client certificates to create a cross-site access-control request
public withCredentials: boolean
// `responseType`
// Returns the type of response data. It allows manual settings to return the type of data. If it is set to an empty string, it will use the default "text" type.
// The enumeration types have the following six types 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
public responseType: string // default: 'text'
// `progressHandler`
// handler xhr progress change event
public progressHandler: Function
// `aborted`
// Identifier requesting termination
public aborted: boolean
// `retryLimit`
// Number of retries for failed requests
public retryLimit: number
// `retryBuffer`
// Retry interval for failed requests
public retryBuffer: number
// `mode`
// There are two request modes in hx: no default
// 'deboucne': Only send the last request within a certain time (debounceTime)
// 'trottle': When a request is sent, it must be separated by a certain time (throttleTime) before the next request can be sent.
public mode: string
// `debounceTime`
// Interval in 'debounce' mode
public debounceTime: number // default: 300
// `throttleTime`
// Interval in 'throttle' mode
public throttleTime: number // default: 3000
}
Response Schema
The response for a request contains the following information.
{
// `data`
// is an object transformed by response schema data
public data: any
// `status`
// is response status code
public status: number
// `statusText`
// is the HTTP status message from the server response `statusText` is the HTTP status message from the server respo
public statusText: string
// `headers`
// the headers that the server responded with
// All header names are lower cased
public headers: object
// `config`
// is the config that was provided to `hajax` for the request
public config: object
// `request`
// HRequest instance which produce this response
public request: HRequest
}
You can access these parameters in the callback function that responds to success and error catching.
hx.get('/api')
.then(function (resp) {
console.log(resp.data);
console.log(resp.status);
console.log(resp.statusText);
console.log(resp.headers);
console.log(resp.config);
})
.catch(function (resp) {
// The same response object can be accessed here, and subsequent operations may be considered in other more appropriate forms.
console.log(resp.data);
console.log(resp.status);
console.log(resp.statusText);
console.log(resp.headers);
console.log(resp.config);
});
Global Config
You can configure the default parameters by configuring global instances, which are mixed into each request.
Config With Instance
hx.config.baseURL = '/api';
hx.config.headers['Auth'] = 'request-auth-token';
// Consider adding a header configuration for the specified request type:
// hx.config.headers.post['Auth'] = 'xxx';
Config With Create
// Configuration settings default settings at creation time
const instance = hx.create({
baseURL: '/api'
});
// Continue to configure on the instance
instance.config.headers['Auth'] = 'request-auth-token';
Configured Priority
The specific configuration on the request will override the global configuration
const instance = hx.create();
// Configure timeouts for all requests
instance.defaults.timeout = 2500;
// The final timeout for this request is 5000 milliseconds, covering the common configuration
instance.get('/longRequest', {
timeout: 5000
});
Interceptor
Before the request is sent and after the request is processed by the user, some specific processing can be done on the request.
// Request interceptor
hx.setRequestInterceptor(function (config) {
config.url = 'http://jsonplaceholder.typicode.com/users/1'
})
// Response interception
hx.setResponseInterceptor(function (resp) {
if (resp.status === 401) window.location = '/login'
})
Request Cancellation
You can terminate a request that is being sent or not sent by the abort
method provided in hx
// Get the returned request instance
const r = hx.get('http://hajax.test/index.php')
.then(function (resp) {
// success handler
}).catch(function (resp) {
// error handler
})
// abort request
r.abort()
Promise Support
The all
method and race
in HAjax
use Promise. If you need to use these two methods, make sure that Promise support exists in the execution environment: native or use [polyfill] (https://github.com/ Stefanpenner/es6-promise)
Related Resources
- Changelog
- Upgrade Guide
- Ecosystem
- Contributing Guide
- Code of Conduct
Main Idea
Solve some problems caused by multi-component and multi-request development under enterprise-level multi-person collaboration, and integrate some best practices in requests
Development Plan
The first edition is mainly to solve the basic request usage scenarios, and can quickly introduce optimization of project implementation requests, which will continue to improve and add more functions
License
MIT