# @rockey2020/next-network

[![npm version](https://img.shields.io/npm/v/@rockey2020/next-network.svg?style=flat-square)](https://www.npmjs.com/package/@rockey2020/next-network)
[![jsdelivr](https://img.shields.io/jsdelivr/npm/hm/@rockey2020/next-network.svg?style=flat-square)](https://cdn.jsdelivr.net/npm/@rockey2020/next-network/dist/browser.js)

A fetch-based, future-oriented construction of a new next-generation network request library, with an advanced request
queue task mechanism, as well as load-balanced request interface, to achieve a breakthrough in the number of concurrent
browser requests, task priority implementation order and other features

docs website:[https://rockey2020.github.io/next-network/](https://rockey2020.github.io/next-network/)

## Table of Contents

- [Features](#Features)
- [Installing](#Installing)
- [Base Example](#Base-Example)
- [NextNetwork Api](#NextNetwork-Api)
- [TaskQueue Api](#TaskQueue-Api)
- [Task Api](#Task-Api)
- [FetchAdapter Api](#FetchAdapter-Api)
- [Types And Config Params](#Types-And-Config-Params)
- [License](#License)

## Features

- Make [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) from the browser
- Make [Fetch](https://nodejs.org/dist/latest-v18.x/docs/api/globals.html#fetch) requests from node.js (need Node.Js version 18+)
- Supports the [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) API
- Intercept request and response
- Concurrent control
- Load balancing
- Break the control on the number of concurrent browser requests
- Cancel requests
- Users can build their own http request method through adapters

## Installing

Using npm:

```bash
$ npm install @rockey2020/next-network -S
```

Using yarn:

```bash
$ yarn add @rockey2020/next-network
```

Using pnpm:

```bash
$ pnpm add @rockey2020/next-network
```

Using jsDelivr CDN:

```html

<script src="https://cdn.jsdelivr.net/npm/@rockey2020/next-network/dist/browser.js"></script>
```

## Base Example

```typescript
import {Task, TaskQueue, FetchAdapter, NextNetwork} from "@rockey2020/next-network"
// for browser useing  const {Task, TaskQueue, FetchAdapter, NextNetwork} = NextNetworkBrowser

const nextNetwork = new NextNetwork({
    fetchAdapterConfig: {
        baseUrl: ["https://www.google.com/"] //string | Array<string>
    }
})

nextNetwork.get("example", {username: "Rockey"}).then(async (res) => {
    console.log(await res.json())
})

nextNetwork.post("example", {username: "Rockey"}).then(async (res) => {
    console.log(await res.json())
})
```

## NextNetwork Api

```
const nextNetwork = new NextNetwork(config?: NextNetworkConfig)

public readonly taskQueue: TaskQueue = new TaskQueue()
public readonly fetchAdapter: FetchAdapter = new FetchAdapter()

public async request(fetchAdapterRequestConfig: FetchAdapterRequestConfig): Promise<any> 
public async get(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>
public async post(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any> 
public async put(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>
public async delete(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>
```

## TaskQueue Api

```
const taskQueue = new TaskQueue(config?: TaskQueueConfig)

public readonly emitter: Emitter<any> = mitt()

/** 已经准备好的任务队列 **/
public readonly readyTaskQueue: Map<string, Task> = new Map()
/** 处理中的任务队列 **/
public readonly processingTaskQueue: Map<string, Task> = new Map()
/** 执行成功的任务队列 **/
public readonly successTaskQueue: Map<string, Task> = new Map()
/** 失败的任务队列 **/
public readonly failTaskQueue: Map<string, Task> = new Map()

/** 执行任务的单位时间 **/
public readonly ExecuteTaskTime: number = 888
/** 最大可执行的任务数量 **/
public readonly MaxExecuteTask: number = 8
/** 最大重试次数 **/
public readonly MaxRetry: number = 8
/** 延迟重试时间 单位：毫秒 **/
public readonly DelayRetryTime: number = 1888
/** 最大保存的执行成功任务数量 **/
public readonly MaxKeepLiveSuccessTask: number = 0

/** 需要处理的系统错误  当错误信息匹配的时候  才会进入重试task流程 否则任务不会重试 即任务重试需要满足两个条件：报错+报错信息匹配 **/
public readonly AllowedRetrySystemErrorNames: Array<string> = []
/** 需要处理的系统错误  当错误信息匹配的时候  才会进入重试task流程 否则任务不会重试 即任务重试需要满足两个条件：报错+报错信息匹配 **/
public readonly AllowedRetrySystemErrorMessages: Array<string> = []
/** 需要处理的系统错误  当错误信息匹配的时候  才会进入重试task流程 否则任务不会重试 即任务重试需要满足两个条件：报错+报错信息匹配 **/
public readonly AllowedRetrySystemErrorCodes: Array<number> = []

/** 创建任务 **/
public createTask(data: CreateTaskParams): Promise<any>
```

## Task Api

```
const task = new Task(config?: TaskConfig)

/** 任务ID **/
public readonly id: string = nanoid(64)
/** 任务执行的异步函数 **/
public readonly asyncFunction: () => Promise<any | void> = async () => ({})
/** 任务优先等级 **/
public readonly level: number = 0
/** 任务失败次数 **/
public failTimes: number = 0
/** 任务执行成功结果 **/
public result: Array<any> = []
/** 任务执行失败报错信息 **/
public error: any = undefined
/** 任务状态 **/
public status: TASK_STATUS = TASK_STATUS.READY

/** 任务状态更新 **/
public async updateStatus(status: TASK_STATUS, message?: any): Promise<void> 
    
/** 执行任务 **/
public async execute(): Promise<any>
```

## FetchAdapter Api

```
const fetchAdapter = new FetchAdapter(config?: FetchAdapterConfig)

public readonly baseRequestConfig: Request = new Request("", {})
public readonly requestTaskControllerList: Map<string, AbortController> = new Map()
public readonly enableCancelRepeatRequest: boolean = true
public readonly enableSpeedTest: boolean = true

public baseUrl: Array<string> = []

/** 测速 **/
public async runSpeedTest(): Promise<void>
    
/** 获取动态url **/
public async getDynamicBaseUrl(): Promise<string> 
    
/** 对url以及query参数进行处理 **/
public async makeUrl(originalUrl, params?: Object | null): Promise<string> 
    
/** 对body参数进行处理 **/
public async makeBody(params?: BodyInit | null): Promise<BodyInit | null> 
    
/** 生成请求token 用来取消重复的请求 **/
public async generateRequestToken(config: FetchAdapterRequestConfig): Promise<string> 
    
/** 生成取消请求的控制信号 **/
public async getRequestSignal(config: FetchAdapterRequestConfig): Promise<AbortSignal | null>
    
/** 构造基本的请求方法 **/
public request(config: FetchAdapterRequestConfig): Promise<Response> 
    
public async get(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>
public async post(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>
            
public async put(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any> 
    
public async delete(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any> 
```

## Types And Config Params

```typescript
enum TASK_STATUS {
    READY = "READY",
    MOVING = "MOVING",
    PROCESSING = "PROCESSING",
    SUCCESS = "SUCCESS",
    FAIL = "FAIL"
}

interface TaskConfig {
    level?: number;
    asyncFunction: () => Promise<any | void>;
    onReady?: (task: Task, message?: any) => Promise<any | void>;
    onMoving?: (task: Task, message?: any) => Promise<any | void>;
    onSuccess?: (task: Task, message?: any) => Promise<any | void>;
    onFail?: (task: Task, message?: any) => Promise<any | void>;
    onProcessing?: (task: Task, message?: any) => Promise<any | void>;
}

/**
 * ## Task **任务实体**
 * **/
declare class Task {
    /** 任务ID **/
    readonly id: string;
    /** 任务执行的异步函数 **/
    readonly asyncFunction: () => Promise<any | void>;
    /** 任务优先等级 **/
    readonly level: number;
    /** 任务失败次数 **/
    failTimes: number;
    /** 任务执行成功结果 **/
    result: Array<any>;
    /** 任务执行失败报错信息 **/
    error: any;
    /** 任务状态 **/
    status: TASK_STATUS;

    constructor(config: TaskConfig);

    /** 任务状态更新 **/
    updateStatus(status: TASK_STATUS, message?: any): Promise<void>;

    /** 执行任务 **/
    execute(): Promise<any>;
}

interface TaskQueueConfig {
    ExecuteTaskTime?: number;
    MaxExecuteTask?: number;
    MaxRetry?: number;
    DelayRetryTime?: number;
    MaxKeepLiveSuccessTask?: number;
    AllowedRetrySystemErrorNames?: Array<string>;
    AllowedRetrySystemErrorMessages?: Array<string>;
    AllowedRetrySystemErrorCodes?: Array<number>;
}

interface CreateTaskParams {
    level?: number;
    asyncFunction: () => Promise<any | void>;
}

/**
 * ## TaskQueue **任务队列管理**
 * **/
declare class TaskQueue {
    readonly emitter: Emitter<any>;
    /** 已经准备好的任务队列 **/
    readonly readyTaskQueue: Map<string, Task>;
    /** 处理中的任务队列 **/
    readonly processingTaskQueue: Map<string, Task>;
    /** 执行成功的任务队列 **/
    readonly successTaskQueue: Map<string, Task>;
    /** 失败的任务队列 **/
    readonly failTaskQueue: Map<string, Task>;
    /** 执行任务的单位时间 **/
    readonly ExecuteTaskTime: number;
    /** 最大可执行的任务数量 **/
    readonly MaxExecuteTask: number;
    /** 最大重试次数 **/
    readonly MaxRetry: number;
    /** 延迟重试时间 单位：毫秒 **/
    readonly DelayRetryTime: number;
    /** 最大保存的执行成功任务数量 **/
    readonly MaxKeepLiveSuccessTask: number;
    /** 需要处理的系统错误  当错误信息匹配的时候  才会进入重试task流程 否则任务不会重试 即任务重试需要满足两个条件：报错+报错信息匹配 **/
    readonly AllowedRetrySystemErrorNames: Array<string>;
    /** 需要处理的系统错误  当错误信息匹配的时候  才会进入重试task流程 否则任务不会重试 即任务重试需要满足两个条件：报错+报错信息匹配 **/
    readonly AllowedRetrySystemErrorMessages: Array<string>;
    /** 需要处理的系统错误  当错误信息匹配的时候  才会进入重试task流程 否则任务不会重试 即任务重试需要满足两个条件：报错+报错信息匹配 **/
    readonly AllowedRetrySystemErrorCodes: Array<number>;

    constructor(config?: TaskQueueConfig);

    /** 创建任务 **/
    createTask(data: CreateTaskParams): Promise<any>;
}

interface FetchAdapterConfig {
    baseUrl?: string | Array<string>;
    enableCancelRepeatRequest?: boolean;
    enableSpeedTest?: boolean;
    requestInitConfig?: RequestInit;
    requestInterceptor?: (params: RequestInterceptorParams) => Promise<RequestInterceptorParams>;
    responseInterceptor?: (response: Response) => Promise<Response | any>;
    errorInterceptor?: (error: Error) => Promise<Error | any>;
}

interface FetchAdapterRequestConfig {
    url: string;
    requestInitConfig?: RequestInit;
    params?: BodyInit | null;
    enableCancelRepeatRequest?: boolean;
}

interface RequestInterceptorParams {
    url: string;
    config: RequestInit;
}

declare class FetchAdapter {
    readonly baseRequestConfig: Request;
    readonly requestTaskControllerList: Map<string, AbortController>;
    readonly enableCancelRepeatRequest: boolean;
    readonly enableSpeedTest: boolean;
    baseUrl: Array<string>;

    constructor(config?: FetchAdapterConfig);

    /** 测速 **/
    runSpeedTest(): Promise<void>;

    /** 获取动态url **/
    getDynamicBaseUrl(): Promise<string>;

    /** 对url以及query参数进行处理 **/
    makeUrl(originalUrl: any, params?: Object | null): Promise<string>;

    /** 对body参数进行处理 **/
    makeBody(params?: BodyInit | null): Promise<BodyInit | null>;

    /** 生成请求token 用来取消重复的请求 **/
    generateRequestToken(config: FetchAdapterRequestConfig): Promise<string>;

    /** 生成取消请求的控制信号 **/
    getRequestSignal(config: FetchAdapterRequestConfig): Promise<AbortSignal | null>;

    /** 构造基本的请求方法 **/
    request(config: FetchAdapterRequestConfig): Promise<Response>;

    get(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>;

    post(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>;

    put(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>;

    delete(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>;
}

interface NextNetworkConfig {
    taskQueue?: TaskQueue;
    taskQueueConfig?: TaskQueueConfig;
    fetchAdapter?: FetchAdapter;
    fetchAdapterConfig?: FetchAdapterConfig;
}

/**
 * ## NextNetwork **网络管理器**
 * **/
declare class NextNetwork {
    readonly taskQueue: TaskQueue;
    readonly fetchAdapter: FetchAdapter;

    constructor(config?: NextNetworkConfig);

    request(fetchAdapterRequestConfig: FetchAdapterRequestConfig): Promise<any>;

    get(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>;

    post(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>;

    put(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>;

    delete(url: string, params?: Object | BodyInit | null, enableCancelRepeatRequest?: boolean): Promise<any>;
}
```

## License

[MIT](LICENSE)
