New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@lion/ajax

Package Overview
Dependencies
Maintainers
1
Versions
82
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@lion/ajax

Thin wrapper around fetch with support for interceptors.

  • 0.6.0
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
246
increased by161.7%
Maintainers
1
Weekly downloads
 
Created
Source

Ajax

ajax is a small wrapper around fetch which:

  • Allows globally registering request and response interceptors
  • Throws on 4xx and 5xx status codes
  • Prevents network request if a request interceptor returns a response
  • Supports a JSON request which automatically encodes/decodes body request and response payload as JSON
  • Adds accept-language header to requests based on application language
  • Adds XSRF header to request if the cookie is present

How to use

Installation

npm i --save @lion/ajax

Relation to fetch

ajax delegates all requests to fetch. ajax.request and ajax.requestJson have the same function signature as window.fetch, you can use any online resource to learn more about fetch. MDN is a great start.

Example requests

GET request
import { ajax } from '@lion/ajax';

const response = await ajax.request('/api/users');
const users = await response.json();
POST request
import { ajax } from '@lion/ajax';

const response = await ajax.request('/api/users', {
  method: 'POST',
  body: JSON.stringify({ username: 'steve' }),
});
const newUser = await response.json();

JSON requests

We usually deal with JSON requests and responses. With requestJson you don't need to specifically stringify the request body or parse the response body:

GET JSON request
import { ajax } from '@lion/ajax';

const { response, body } = await ajax.requestJson('/api/users');
POST JSON request
import { ajax } from '@lion/ajax';

const { response, body } = await ajax.requestJson('/api/users', {
  method: 'POST',
  body: { username: 'steve' },
});

Error handling

Different from fetch, ajax throws when the server returns a 4xx or 5xx, returning the request and response:

import { ajax } from '@lion/ajax';

try {
  const users = await ajax.requestJson('/api/users');
} catch (error) {
  if (error.response) {
    if (error.response.status === 400) {
      // handle a specific status code, for example 400 bad request
    } else {
      console.error(error);
    }
  } else {
    // an error happened before receiving a response, ex. an incorrect request or network error
    console.error(error);
  }
}

Ajax Cache

A caching library that uses lion-web/ajax and adds cache interceptors to provide caching for use in frontend services.

Technical documentation and decisions can be found in ./docs/technical-docs.md

Getting started

Consume the global ajax instance and add the interceptors to it, using a cache configuration which is applied on application level. If a developer wants to add specifics to cache behavior they have to provide a cache config per action (get, post, etc.) via cacheOptions field of local ajax config, see examples below.

Note: make sure to add the interceptors only once. This is usually done on app-level

import {
  ajax,
  cacheRequestInterceptorFactory,
  cacheResponseInterceptorFactory,
} from '@lion-web/ajax.js';

const globalCacheOptions = {
  useCache: true,
  timeToLive: 1000 * 60 * 5, // 5 minutes
};
// Cache is removed each time an identifier changes,
// for instance when a current user is logged out
const getCacheIdentifier = () => getActiveProfile().profileId;

ajax.addRequestInterceptor(cacheRequestInterceptorFactory(getCacheIdentifier, globalCacheOptions));
ajax.addResponseInterceptor(
  cacheResponseInterceptorFactory(getCacheIdentifier, globalCacheOptions),
);

const { response, body } = await ajax.requestJson('/my-url');

Ajax cache example

import {
  ajax,
  cacheRequestInterceptorFactory,
  cacheResponseInterceptorFactory,
} from '@lion-web/ajax';

const getCacheIdentifier = () => getActiveProfile().profileId;

const globalCacheOptions = {
  useCache: false,
  timeToLive: 50, // default: one hour (the cache instance will be replaced in 1 hour, regardless of this setting)
  methods: ['get'], // default: ['get'] NOTE for now only 'get' is supported
  // requestIdentificationFn: (requestConfig) => { }, // see docs below for more info
  // invalidateUrls: [], see docs below for more info
  // invalidateUrlsRegex: RegExp, // see docs below for more info
};

// pass a function to the interceptorFactory that retrieves a cache identifier
// ajax.interceptors.request.use(cacheRequestInterceptorFactory(getCacheIdentifier, cacheOptions));
// ajax.interceptors.response.use(
//   cacheResponseInterceptorFactory(getCacheIdentifier, cacheOptions),
// );

class TodoService {
  constructor() {
    this.localAjaxConfig = {
      cacheOptions: {
        invalidateUrls: ['/api/todosbykeyword'], // default: []
      },
    };
  }

  /**
   * Returns all todos from cache if not older than 5 minutes
   */
  getTodos() {
    return ajax.requestJson(`/api/todos`, this.localAjaxConfig);
  }

  /**
   *
   */
  getTodosByKeyword(keyword) {
    return ajax.requestJson(`/api/todosbykeyword/${keyword}`, this.localAjaxConfig);
  }

  /**
   * Creates new todo and invalidates cache.
   * `getTodos` will NOT take the response from cache
   */
  saveTodo(todo) {
    return ajax.requestJson(`/api/todos`, { method: 'POST', body: todo, ...this.localAjaxConfig });
  }
}

If a value returned by cacheIdentifier changes the cache is reset. We avoid situation of accessing old cache and proactively clean it, for instance when a user session is ended.

Ajax cache Options

const cacheOptions = {
  // `useCache`: determines wether or not to use the cache
  // can be boolean
  // default: false
  useCache: true,

  // `timeToLive`: is the time the cache should be kept in ms
  // default: 0
  // Note: regardless of this setting, the cache instance holding all the caches
  //       will be invalidated after one hour
  timeToLive: 1000 * 60 * 5,

  // `methods`: an array of methods on which this configuration is applied
  // Note: when `useCache` is `false` this will not be used
  // NOTE: ONLY GET IS SUPPORTED
  // default: ['get']
  methods: ['get'],

  // `invalidateUrls`: an array of strings that for each string that partially
  // occurs as key in the cache, will be removed
  // default: []
  // Note: can be invalidated only by non-get request to the same url
  invalidateUrls: ['/api/todosbykeyword'],

  // `invalidateUrlsRegex`: a RegExp object to match and delete
  // each matched key in the cache
  // Note: can be invalidated only by non-get request to the same url
  invalidateUrlsRegex: /posts/

  // `requestIdentificationFn`: a function to provide a string that should be
  // taken as a key in the cache.
  // This can be used to cache post-requests.
  // default: (requestConfig, searchParamsSerializer) => url + params
  requestIdentificationFn: (request, serializer) => {
    return `${request.url}?${serializer(request.params)}`;
  },
};

Considerations

Fetch Polyfill

For IE11 you will need a polyfill for fetch. You should add this on your top level layer, e.g. your application.

This is the polyfill we recommend. It also has a section for polyfilling AbortController

Keywords

FAQs

Package last updated on 16 Feb 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc