-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
renjiazheng
committed
Apr 22, 2020
0 parents
commit f2f7ea3
Showing
15 changed files
with
7,176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "react-app", | ||
"rules": {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
node_modules | ||
dist | ||
.cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
### intro | ||
|
||
a lightweight fetch lib with middleware inspire by koa | ||
|
||
|
||
|
||
### quick start | ||
|
||
``` | ||
yarn add @jarzzzi/rufetch | ||
``` | ||
|
||
|
||
### example | ||
|
||
```code | ||
const http = new Rufetch({ | ||
baseURL: 'https://github.com/api', | ||
}) | ||
const getUser = (name) => { | ||
return http.get(`/user/${name}`) | ||
} | ||
const getReps = (name, page) => { | ||
return http.get(`/user/${name}`, {params: {page}}) | ||
} | ||
const createReps = (name, data) => { | ||
return http.post(`/user/${name}`, {data}) | ||
} | ||
``` | ||
|
||
### middleware | ||
- built in middleware | ||
- cache | ||
- fetch | ||
|
||
```code | ||
http.use(async (ctx: any, next: any) => { | ||
await next() | ||
const {error} = ctx.res | ||
if (error?.status >= 400 && error?.status < 500) { | ||
console.error('client error') | ||
} | ||
if (error?.status >= 500) { | ||
console.error('server error') | ||
} | ||
if (error === 'fetch timeout') { | ||
console.error('fetch timeout') | ||
} | ||
}) | ||
``` | ||
|
||
### api | ||
- options | ||
- baseURL | ||
- timeout: default 15000 | ||
- params: url search params | ||
- data: body alias | ||
- responseType: default json, arrayBuffer, blob, json, text, formData, stream... | ||
- cacheOptions | ||
- cache: boolean | ||
- expiredAge: default 5000 | ||
- body | ||
- cache | ||
- credentials | ||
- headers | ||
- integrity | ||
- keepalive | ||
- method | ||
- mode | ||
- redirect | ||
- referrer | ||
- referrerPolicy | ||
- signal | ||
- window | ||
- new (options) | ||
- instance.get | ||
- instance.post | ||
- instance.put | ||
- instance.delete | ||
- instance.head | ||
- instance.use: add middleware |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Document</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script src="./index.tsx"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"name": "@jarzzzi/rufetch", | ||
"version": "1.0.0", | ||
"description": "a fetch lib with middleware inspire by koa", | ||
"entry": "src/index.ts", | ||
"module": "dist/esm/index.js", | ||
"main": "dist/cjs/index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1", | ||
"demo": "parcel serve ./demo/index.html", | ||
"build": "rollup -c rollup.config.ts", | ||
"version": "npm version patch", | ||
"publish": "npm publish --access=public" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/Jarweb/rufetch.git" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"bugs": { | ||
"url": "https://github.com/Jarweb/rufetch/issues" | ||
}, | ||
"homepage": "https://github.com/Jarweb/rufetch#readme", | ||
"devDependencies": { | ||
"@jarzzzi/nidavel": "^1.0.6", | ||
"rollup": "^2.6.1", | ||
"typescript": "^3.8.3" | ||
}, | ||
"dependencies": { | ||
"isomorphic-fetch": "^2.2.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import configRollup from '@jarzzzi/nidavel' | ||
|
||
export default configRollup({ | ||
target: ['esm'], | ||
input: './src/index.ts', | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// 默认过期时长,只有 http get、显式设置 cache 的数据请求才进行缓存 | ||
const EXPIRE_AGE = 5000 | ||
// 会打包出重复的 2份代码,每份代码初始化会重置 window._request_cache_ | ||
window._request_cache_ = window._request_cache_ || {} | ||
|
||
export function getRequestCache(key: string) { | ||
const now = Date.now() | ||
// 过期 | ||
if (window._request_cache_[key] && | ||
window._request_cache_[key]?.status === 'success' && | ||
(window._request_cache_[key]?.createTime as number) + (window._request_cache_[key]?.expiredAge as number) <= now | ||
) { | ||
removeRequestCache(key) | ||
} | ||
return window._request_cache_[key] | ||
} | ||
|
||
export function setRequestCache(key: string, value: any) { | ||
const now = Date.now() | ||
// 未过期 | ||
if (window._request_cache_[key] && | ||
window._request_cache_[key]?.status === 'success' && | ||
(window._request_cache_[key]?.createTime as number) + (window._request_cache_[key]?.expiredAge as number) > now) return; | ||
|
||
window._request_cache_[key] = { | ||
expiredAge: window._request_cache_[key]?.expiredAge || EXPIRE_AGE, | ||
status: 'success', | ||
createTime: Date.now(), | ||
value: value, | ||
} | ||
} | ||
|
||
export function pendingRequestCache(key: string, expiredAge?: number) { | ||
window._request_cache_[key] = { | ||
status: 'pending', | ||
createTime: Date.now(), | ||
expiredAge: expiredAge || EXPIRE_AGE, | ||
value: undefined, | ||
} | ||
} | ||
|
||
export function removeRequestCache(key: string) { | ||
window._request_cache_[key] = undefined | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
export default function compose (middleware: any[]) { | ||
let index = -1 | ||
|
||
return function (context: any, next: any) { | ||
function dispatch (i: number): any { | ||
if (i <= index) { | ||
return Promise.reject(new Error('')) | ||
} | ||
|
||
index = i | ||
|
||
let fn = middleware[i] | ||
if (i === middleware.length) fn = next; | ||
if (!fn) return Promise.resolve() | ||
|
||
try { | ||
return Promise.resolve(fn(context, dispatch.bind(null, i + 1))) | ||
} catch (error) { | ||
return Promise.reject(error) | ||
} | ||
} | ||
|
||
return dispatch(0) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
import compose from './compose' | ||
import middlewareFetch from './middlewareFetch' | ||
import middlewareCache from './middlewareCache' | ||
|
||
interface RufetchOption { | ||
baseURL?: string, | ||
timeout?: number, | ||
// like get... | ||
params?: RequestInit['body'], | ||
// like post | ||
data?: RequestInit['body'], | ||
// arrayBuffer, blob, json, text, formData, stream..., default json | ||
responseType?: string, | ||
// built in cache, not native request cache | ||
cacheOptions?: { | ||
cache: boolean, | ||
expiredAge?: number, | ||
}, | ||
// native request config | ||
body?: RequestInit['body'], | ||
cache?: RequestInit['cache'], | ||
credentials?: RequestInit['credentials'], | ||
headers?: RequestInit['headers'], | ||
integrity?: RequestInit['integrity'], | ||
keepalive?: RequestInit['keepalive'], | ||
method?: RequestInit['method'], | ||
mode?: RequestInit['mode'], | ||
redirect?: RequestInit['redirect'], | ||
referrer?: RequestInit['referrer'], | ||
referrerPolicy?: RequestInit['referrerPolicy'], | ||
signal?: RequestInit['signal'], | ||
window?: RequestInit['window'], | ||
} | ||
|
||
export default class Rufetch { | ||
private options: RufetchOption = {} | ||
private middlewares: Function[] = [] | ||
|
||
constructor(options: RufetchOption) { | ||
this.options = options | ||
} | ||
|
||
use = (middleware: any) => { | ||
this.middlewares.push(middleware) | ||
return this | ||
} | ||
|
||
preRequest = (method: string) => { | ||
return ( url: string, rufetch?: RufetchOption) => { | ||
const { | ||
baseURL: defaultBaseURL, | ||
timeout: defaultTimeout, | ||
params: defaultParams, | ||
data: defaultData, | ||
responseType: defaultResponseType, | ||
cacheOptions: defaultCacheOptions, | ||
body: defaultBody, | ||
cache: defaultCache, | ||
credentials: defaultCredentials, | ||
headers: defaultHeaders, | ||
integrity: defaultIntegrity, | ||
keepalive: defaultKeepalive, | ||
method: defaultMethod, | ||
mode: defaultMode, | ||
redirect: defaultRedirect, | ||
referrer: defaultReferrer, | ||
referrerPolicy: defaultReferrerPolicy, | ||
signal: defaultSignal, | ||
window: defaultWindow, | ||
...defaultRest | ||
} = this.options | ||
|
||
const { | ||
baseURL, | ||
timeout, | ||
params, | ||
data, | ||
responseType, | ||
cacheOptions, | ||
body, | ||
cache, | ||
credentials, | ||
headers, | ||
integrity, | ||
keepalive, | ||
method, | ||
mode, | ||
redirect, | ||
referrer, | ||
referrerPolicy, | ||
signal, | ||
window, | ||
...restOptions | ||
} = rufetch || {} | ||
|
||
const defaultRequestInit: RequestInit = { | ||
body: defaultBody, | ||
cache: defaultCache, | ||
credentials: defaultCredentials, | ||
headers: defaultHeaders, | ||
integrity: defaultIntegrity, | ||
keepalive: defaultKeepalive, | ||
method: defaultMethod, | ||
mode: defaultMode, | ||
redirect: defaultRedirect, | ||
referrer: defaultReferrer, | ||
referrerPolicy: defaultReferrerPolicy, | ||
signal: defaultSignal, | ||
window: defaultWindow, | ||
} | ||
const requestInit: RequestInit = { | ||
body, | ||
cache, | ||
credentials, | ||
headers, | ||
integrity, | ||
keepalive, | ||
method, | ||
mode, | ||
redirect, | ||
referrer, | ||
referrerPolicy, | ||
signal, | ||
window, | ||
} | ||
requestInit.method = method | ||
|
||
const middlewares = [ | ||
...this.middlewares, | ||
middlewareCache, | ||
middlewareFetch | ||
] | ||
const ctx: any = {} | ||
|
||
const rurl = url.indexOf(defaultBaseURL || '') > -1 ? url : defaultBaseURL + url | ||
const reqInit = Object.assign({}, defaultRequestInit, requestInit) | ||
const rbody = Object.assign({}, data, body) | ||
|
||
reqInit.body = rbody ? rbody : defaultBody | ||
reqInit.headers = Object.assign({}, defaultHeaders, headers) | ||
|
||
ctx.req = { | ||
url: rurl, | ||
method, | ||
timeout: timeout ? timeout : (defaultTimeout || 3000), | ||
params: params ? params : defaultParams, | ||
requestInit: reqInit, | ||
...Object.assign({}, defaultRest, restOptions), | ||
} | ||
ctx.res = {} | ||
|
||
return new Promise(async (resolve, reject) => { | ||
try { | ||
await compose(middlewares)(ctx, null) | ||
resolve(ctx.res.data) | ||
} catch (error) { | ||
if (!error) return; | ||
throw error | ||
} | ||
}) | ||
} | ||
} | ||
|
||
get = this.preRequest('get') | ||
post = this.preRequest('post') | ||
put = this.preRequest('put') | ||
delete = this.preRequest('delete') | ||
head = this.preRequest('head') | ||
} | ||
|
Oops, something went wrong.