npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

legions-fetch

v0.1.1

Published

基础请求库

Downloads

2

Readme

legions-fetch

此库已经过严格的单元测试,请放心使用

Promise based HTTP client for the browser and node.js

what is legions-fetch?

legions-request 是一个支持浏览器及服务端的 http 请求工具库

Features

  • 高版本浏览器直接基于 fetch
  • 低版本不支持 fetch 时,自动降级兼容 fetch 所有特性
  • nodejs 中通过 http 发送请求
  • Supports the Promise API
  • 支持注入 request,respone,reject 等拦截器
  • 超时自动中断请求

Installing

Using npm and yarn :

npm i legions-requset -S

or

yarn add legions-requset -S

Using jsDelivr CDN:

<script src="dist/index.iife.js"></script>

Example

import { get, post } from 'legions-fetch';
get({
  url: '/user?ID=12345',
}).then(function (response) {
  // handle success
  console.log(response);
});

POST Requests

How to perfrom POST requests with legions-fetch

Performing a POST request

import { get, post } from 'legions-fetch';
post({
  url: '/user',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone',
  },
}).then(function (response) {
  console.log(response);
});

Performing multiple concurrent requests

function getUserAccount() {
  return get({
    url: '/user/12345',
  });
}

function getUserPermissions() {
  return get({
    url: '/user/12345/permissions',
  });
}

Promise.all([getUserAccount(), getUserPermissions()]).then(function (results) {
  const acct = results[0];
  const perm = results[1];
});

legions-request api

The legions-request API Reference

legionFetch.instance.request(config)

// Send a POST request
legionFetch.instance.request({
  method: 'post',
  url: '/user/12345',
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone',
  },
});
// GET request for remote image in node.js
legionFetch.instance
  .request({
    method: 'get',
    url: 'http://bit.ly/2mTM3nY',
    responseType: 'stream',
  })
  .then(function (response) {
    response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'));
  });

Request method aliases

For convenience aliases have been provided for all supported request methods.

  • legionFetch.instance.request({method: 'get'})
  • legionFetch.instance.request({method: 'delete'})
  • legionFetch.instance.request({method: 'head'})
  • legionFetch.instance.request({method: 'options'})
  • legionFetch.instance.request({method: 'post'})
  • legionFetch.instance.request({method: 'put'})
  • legionFetch.instance.request({method: 'patch'})
  • legionFetch.instance.get(config)
  • legionFetch.instance.post(config)

The legions-request Instance

Creating an instance

You can create a new instance of axios with a custom config.

import { legionFetch } from 'legions-fetch';
const instance = legionFetch.create();

Instance methods

  • instance.request({method: 'get'})
  • instance.request({method: 'delete'})
  • instance.request({method: 'head'})
  • instance.request({method: 'options'})
  • instance.request({method: 'post'})
  • instance.request({method: 'put'})
  • instance.request({method: 'patch'})
  • instance.get(config)
  • instance.post(config)

Request Config

These are the available config options for making requests. Only the url is required. Requests will default to GET if method is not specified.

{
  // `url` is the server URL that will be used for the request
  url: '/user',

  // `method` is the request method to be used when making the request
  method: 'get', // default

  // `baseURL` will be prepended to `url` unless `url` is absolute.
  // It can be convenient to set `baseURL` for an instance of axios to pass relative URLs
  // to methods of that instance.
  baseURL: 'https://some-domain.com/api/',

  // 发送前对配置数据进行处理
  transformRequest: function (config, url) {
    // Do whatever you want to transform the data

    return config;
  },


  // `headers` are custom headers to be sent
  headers: {'X-Requested-With': 'XMLHttpRequest'},

  // `params` are the URL parameters to be sent with the request
  // Must be a plain object or a URLSearchParams object
  // NOTE: params that are null or undefined are not rendered in the URL.
  params: {
    ID: 12345
  },

  // `data` is the data to be sent as the request body
  // Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'
  // When no `transformRequest` is set, must be of one of the following types:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - Browser only: FormData, File, Blob
  // - Node only: Stream, Buffer
  data: {
    firstName: 'Fred'
  },

  // syntax alternative to send data into the body
  // method post
  // only the value is sent, not the key
  data: 'Country=Brasil&City=Belo Horizonte',

  // `timeout` specifies the number of milliseconds before the request times out.
  // If the request takes longer than `timeout`, the request will be aborted.
  timeout: 1000, // default is `0` (no timeout)

  // should be made using credentials
  // "include" | "omit" | "same-origin"
  credentials: 'include', // default

  // `responseType` indicates the type of data that the server will respond with
  // options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
  //   browser only: 'blob'
  responseType: 'json', // default


  // `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
  xsrfCookieName: 'XSRF-TOKEN', // default

  // `xsrfHeaderName` is the name of the http header that carries the xsrf token value
  xsrfHeaderName: 'X-XSRF-TOKEN', // default


  // `maxRedirects` defines the maximum number of redirects to follow in node.js.
  // If set to 0, no redirects will be followed.
  maxRedirects: 5, // default
  // data 数据是否默认转json,默认true,只有在data是对象时才会执行
  isDataToConvertJson:boolean,

  /**
     * A cryptographic hash of the resource to be fetched by request. Sets request's integrity.
     */
    integrity?: string,
    /**
     * A boolean to set request's keepalive.
     */
    keepalive?: boolean,
    /**
     * A string to set request's method.
     */
    method?: string,
    /**
     * A string to indicate whether the request will use CORS, or will be restricted to same-origin URLs. Sets request's mode.
     */
    mode?: RequestMode,
    /**
     * A string indicating whether request follows redirects, results in an error upon encountering a redirect, or returns the redirect (in an opaque fashion). Sets request's redirect.
     */
    redirect?: RequestRedirect,
    /**
     * A string whose value is a same-origin URL, "about:client", or the empty string, to set request's referrer.
     */
    referrer?: string,
    /**
     * A referrer policy to set request's referrerPolicy.
     */
    referrerPolicy?: ReferrerPolicy,
    /**
     * An AbortSignal to set request's signal.
     */
    signal?: AbortSignal | null,
}

拦截器

在请求或响应被 then 处理前拦截它们。

use

legionFetch.instance.register({
  request: (config) => {
    config.credentials = 'omit';
    return config;
  },
  response: (res) => {
    return res;
  },
  responseReject: (res) => {
    return res;
  },
});

默认注入的拦截器

request

const defaultRequest = [
  {
    request: (configs /**  传入进来的配置参数*/) => {
      //注册拦截请求, 默认所有请求返回json格式
      /**  设置默认request */
      let options = {
        headers: {
          'content-type': 'application/json',
        },
        credentials: 'include',
      };
      /**  使用传入进来的配置覆盖默认配置*/
      let config = mergeConfig(options, { ...tranfromOptions(configs.options), url: configs.url });
      return config;
    },
  },
  {
    request: (configs: IRequestConfigs) => {
      //注册请求, 请求默认携带验证参数
      let options = {
        /**  超时时间*/
        timeout: 50000,
      };
      let config = mergeConfig(options, configs);
      return config;
    },
  },
];

response

defaultResponse = [
  {
    response: (response, config: IRequestConfigs) => {
      return response;
    },
  },
  {
    //response已经被反序列化, 返回了对应对象
    response: (response, config: IRequestConfigs) => {
      if (config && config.responseType === 'json') {
        const res = response.json();
        return res;
      }
      return response;
    },
  },
];

Reject

[
  {
    //@ts-ignore
    responseReject: (response, config) => {
      let error: any = {};
      if (response instanceof FetchError) {
        error = {
          name: response.name,
          type: response.type,
          code: response.code,
          message: response.message,
        };
      } else if (response instanceof Error) {
        error = {
          name: response.name,
          type: response.name,
          stack: response.stack,
          message: response.message,
        };
      }
      return Promise.resolve(
        new ResponseResult({
          success: false,
          message: JSON.stringify(error),
          code: error.type === 'request-timeout' ? DataRequestStateEnum.Timeout.toString() : '500',
          data: null,
        }),
      );
    },
  },
];

lrequestContainer

此方法初步方案借鉴社区方案实现,后续会迭代完善

所做事情

  1. 保证在相同的 HTTP 请求在同一个时间段内只有一个请求发生
  2. 所有的请求都经过这个容器,这样有助于我们去管理所有发生的请求

举例场景

  1. 单应用中,我们做组件开发,每一个组件应该独立完成自己的工作. 那么组件之间在绝大多数情况下是没有任何通信的. 那么如果一个页面存在任意 2 个或多个组件在几 乎同一个时间内发出相同的 http 请求, 这样无疑会浪费且会增加服务器负载. 为了处理这个问题, lrequestContainer(请求容器)保证同一个时刻有且仅有一个 http 请求, 无论组件发送多少请求.

  2. 对于单页面应用, 因为所有请求都经过容器,在我们发送一个耗时请求时,这个时候我们想离开当前页面. 但是任何发生在先前页面的请求会难以管理/取消 . lrequestContainer(请求容器)提供了一个非常好的方式让开发者能 轻易管理到这些请求.

use

import { lrequestContainer } from 'legions-fetch';
//type RequestParamType = {url: 'www.example.com/api', data: {token:123}, method: 'get'};
//promiseFn:() =>Promise<any>, e.g.  promiseFn = ()=>$.ajax(...);
const promiseState = requestContainer.put(JSON.stringify(requestParam), promiseFn);

并发相同请求

import { lrequestContainer } from 'legions-fetch';

function httpRequest(duration: number): Promise<void> {
  return new Promise(() => setTimeout(resolve, number));
}

const requestContainer = RequestContainer.getInstance();

//假设第一个请求请求2秒
const requestParam1 = { url: 'www.example.com/api', data: { token: 123 }, method: 'get' };
const promiseFn1 = () => httpRequest(2000);
const promiseState1 = requestContainer.put(JSON.stringify(requestParam1), promiseFn1);

//假设第二个请求4秒, 其实并没有关系, 因为第一个请求会决定这后面请求只会是2秒完成
const requestParam2 = { url: 'www.example.com/api', data: { token: 123 }, method: 'get' };
const promiseFn2 = () => httpRequest(4000);
const promiseState2 = requestContainer.put(JSON.stringify(requestParam2), promiseFn2);

/**
 * 由于他们使用相同参数请求, 那么我们可以认为他们是相同的请求. 所以如果<请求1>发出,
 * 请求2会被拦截, 并指向请求1, 也就是说他们两会共享同一个promise.
 * 那么这样就能确保整一个请求周期有且只有一个真正的对外请求
 */

版权

MIT