更新支持注入

master
yutent 2022-03-22 19:04:58 +08:00
parent 6909c15ffb
commit 8ad97d1e1d
5 changed files with 137 additions and 51 deletions

10
.prettierrc.yaml Normal file
View File

@ -0,0 +1,10 @@
jsxBracketSameLine: true
jsxSingleQuote: true
semi: false
singleQuote: true
printWidth: 100
useTabs: false
tabWidth: 2
trailingComma: none
bracketSpacing: true
arrowParens: avoid

View File

@ -59,7 +59,7 @@ f1('/get_list', {body: {page: 1}})
> 发起一个网络请求, options的参数如下。 同时支持配置公共域名, 公共参数。 > 发起一个网络请求, options的参数如下。 同时支持配置公共域名, 公共参数。
+ method<String> 默认GET, 可选GET/POST/PUT/DELETE... + method<String> 默认GET, 可选GET/POST/PUT/DELETE...
+ body<Any> 要发送的数据, 如果是GET方式, 会被自动拼接到url上 + body<Any> 要发送的数据, 如果是不允许有`body`的方式, 会被自动拼接到url上
+ cache<String> 是否缓存, + cache<String> 是否缓存,
+ credentials<String/Boolean> 是否校验 + credentials<String/Boolean> 是否校验
+ signal<Object> 网络控制信号, 可用于中断请求 + signal<Object> 网络控制信号, 可用于中断请求
@ -67,10 +67,32 @@ f1('/get_list', {body: {page: 1}})
```js ```js
fetch.BASE_URL = '//192.168.1.100' fetch.BASE_URL = '//192.168.1.100'
fetch.__INIT__ = {headers: {token: 123456}} fetch.__INIT__ = {headers: {token: 123456}} // 2.x 之后将废弃, 不推荐使用了
// 1.2.0开始支持注入
fetch.inject.request(function(conf) {
// 无需返回值, 但需要注意这是引用类型,不要对带个conf赋值
conf.headers.token = 123456
})
// 响应注入, 需要有返回值
fetch.inject.response(function(res) {
return res.json()
})
``` ```
2. fetch.create([base_url][, options<Object>]) 2. fetch.create([BASE_URL][, options<Object>])
> 创建一个新的fetch实例 > 创建一个新的fetch实例
```js
var another = fetch.create('//192.168.1.101')
// 新创建的实例, 也支持注入
another.inject.request(function(conf) {
conf.headers.token = 123456
})
another.inject.response(function(res) {
return res.json()
})
```

View File

@ -1,9 +1,11 @@
{ {
"name": "@bytedo/fetch", "name": "@bytedo/fetch",
"version": "1.1.3", "version": "1.2.0",
"description": "全新的ajax封装。分2个版本, 一个基于XMLHttpRequest, 一个基于window.fetch", "description": "全新的ajax封装。分2个版本, 一个基于XMLHttpRequest, 一个基于window.fetch",
"main": "dist/index.js", "main": "dist/index.js",
"files": ["dist/*"], "files": [
"dist/*"
],
"scripts": { "scripts": {
"start": "node ./build.js" "start": "node ./build.js"
}, },
@ -11,7 +13,12 @@
"type": "git", "type": "git",
"url": "git+https://github.com/bytedo/fetch.git" "url": "git+https://github.com/bytedo/fetch.git"
}, },
"keywords": ["fetch", "axois", "request", "ajax"], "keywords": [
"fetch",
"axios",
"request",
"ajax"
],
"author": "yutent", "author": "yutent",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {

View File

@ -24,9 +24,9 @@ const ERRORS = {
10504: 'Connected timeout' 10504: 'Connected timeout'
} }
Promise.defer = function() { Promise.defer = function () {
var _ = {} var _ = {}
_.promise = new Promise(function(y, n) { _.promise = new Promise(function (y, n) {
_.resolve = y _.resolve = y
_.reject = n _.reject = n
}) })
@ -34,7 +34,7 @@ Promise.defer = function() {
} }
class _Request { class _Request {
constructor(url = '', options = {}, { BASE_URL, __INIT__ }) { constructor(url = '', options = {}, { BASE_URL, __INIT__ }, owner) {
if (!url) { if (!url) {
throw new Error(ERRORS[10001]) throw new Error(ERRORS[10001])
} }
@ -52,6 +52,7 @@ class _Request {
this.xhr = new XMLHttpRequest() this.xhr = new XMLHttpRequest()
this.defer = Promise.defer() this.defer = Promise.defer()
this._owner = owner
this.options = { this.options = {
headers: { headers: {
@ -69,11 +70,11 @@ class _Request {
var control = new AbortController() var control = new AbortController()
options.signal = control.signal options.signal = control.signal
} }
this.defer.promise.abort = function() { this.defer.promise.abort = function () {
control.abort() control.abort()
} }
var headers = this.options.headers let headers = this.options.headers
if (__INIT__.headers) { if (__INIT__.headers) {
Object.assign(headers, __INIT__.headers) Object.assign(headers, __INIT__.headers)
@ -86,6 +87,10 @@ class _Request {
Object.assign(this.options, __INIT__, options, { url, headers }) Object.assign(this.options, __INIT__, options, { url, headers })
if (owner._inject_req) {
owner._inject_req(this.options)
}
this.__next__() this.__next__()
return this.defer.promise return this.defer.promise
} }
@ -155,8 +160,8 @@ class _Request {
let $a = document.createElement('a') let $a = document.createElement('a')
$a.href = options.url $a.href = options.url
crossDomain = crossDomain = location.protocol !== $a.protocol || location.host !== $a.host
location.protocol !== $a.protocol || location.host !== $a.host $a = null
} catch (err) {} } catch (err) {}
if (crossDomain) { if (crossDomain) {
@ -176,8 +181,7 @@ class _Request {
options.url += (~options.url.indexOf('?') ? '&' : '?') + params options.url += (~options.url.indexOf('?') ? '&' : '?') + params
} }
if (options.cache === 'no-store') { if (options.cache === 'no-store') {
options.url += options.url += (~options.url.indexOf('?') ? '&' : '?') + '_t_=' + Date.now()
(~options.url.indexOf('?') ? '&' : '?') + '_t_=' + Date.now()
} }
} else { } else {
if (!hasAttach) { if (!hasAttach) {
@ -197,16 +201,15 @@ class _Request {
// 6.1 // 6.1
this.xhr.onreadystatechange = ev => { this.xhr.onreadystatechange = ev => {
if (options.timeout > 0) { if (options.timeout > 0) {
options['time' + this.xhr.readyState] = ev.timeStamp this['time' + this.xhr.readyState] = ev.timeStamp
if (this.xhr.readyState === 4) { if (this.xhr.readyState === 4) {
options.isTimeout = options.time4 - options.time1 > options.timeout options.isTimeout = this.time4 - this.time1 > options.timeout
} }
} }
if (this.xhr.readyState !== 4) { if (this.xhr.readyState !== 4) {
return return
} }
this.__dispatch__(options.isTimeout) this.__dispatch__(options.isTimeout)
} }
@ -285,6 +288,10 @@ class _Request {
var { body, status, statusText, headers } = result var { body, status, statusText, headers } = result
var response = new Response(body, { status, statusText, headers }) var response = new Response(body, { status, statusText, headers })
if (this._owner._inject_res) {
response = this._owner._inject_res(response)
}
if (isSucc) { if (isSucc) {
this.defer.resolve(response) this.defer.resolve(response)
} else { } else {
@ -322,17 +329,37 @@ class _Request {
} }
} }
const _fetch = function(url, options) { const _fetch = function (url, options) {
return new _Request(url, options, { return new _Request(
url,
options,
{
BASE_URL: _fetch.BASE_URL, BASE_URL: _fetch.BASE_URL,
__INIT__: _fetch.__INIT__ || Object.create(null) __INIT__: _fetch.__INIT__ || Object.create(null)
}) },
_fetch
)
} }
_fetch.create = function(BASE_URL, __INIT__ = Object.create(null)) { function inject(target) {
return function(url, options) { target.inject = {
return new _Request(url, options, { BASE_URL, __INIT__ }) request(callback) {
target._inject_req = callback
},
response(callback) {
target._inject_res = callback
}
} }
} }
_fetch.create = function (BASE_URL, __INIT__ = Object.create(null)) {
var another = function (url, options) {
return new _Request(url, options, { BASE_URL, __INIT__ }, another)
}
inject(another)
return another
}
inject(_fetch)
export default _fetch export default _fetch

View File

@ -6,7 +6,7 @@
import { Format, toS } from './lib/format.js' import { Format, toS } from './lib/format.js'
const NATIVE_FETCH = window.fetch const nativeFetch = window.fetch
const NOBODY_METHODS = ['GET', 'HEAD'] const NOBODY_METHODS = ['GET', 'HEAD']
const FORM_TYPES = { const FORM_TYPES = {
form: 'application/x-www-form-urlencoded; charset=UTF-8', form: 'application/x-www-form-urlencoded; charset=UTF-8',
@ -26,7 +26,7 @@ const ERRORS = {
} }
class _Request { class _Request {
constructor(url = '', options = {}, { BASE_URL, __INIT__ }) { constructor(url = '', options = {}, { BASE_URL, __INIT__ }, owner) {
if (!url) { if (!url) {
throw new Error(ERRORS[10001]) throw new Error(ERRORS[10001])
} }
@ -42,6 +42,8 @@ class _Request {
options.method = (options.method || 'get').toUpperCase() options.method = (options.method || 'get').toUpperCase()
this._owner = owner
this.options = { this.options = {
headers: { headers: {
'X-Requested-With': 'XMLHttpRequest', 'X-Requested-With': 'XMLHttpRequest',
@ -58,7 +60,7 @@ class _Request {
options.signal = this.control.signal options.signal = this.control.signal
} }
var headers = this.options.headers let headers = this.options.headers
if (__INIT__.headers) { if (__INIT__.headers) {
Object.assign(headers, __INIT__.headers) Object.assign(headers, __INIT__.headers)
@ -71,6 +73,10 @@ class _Request {
Object.assign(this.options, __INIT__, options, { url, headers }) Object.assign(this.options, __INIT__, options, { url, headers })
if (owner._inject_req) {
owner._inject_req(this.options)
}
return this.__next__() return this.__next__()
} }
@ -133,8 +139,8 @@ class _Request {
let $a = document.createElement('a') let $a = document.createElement('a')
$a.href = options.url $a.href = options.url
crossDomain = crossDomain = location.protocol !== $a.protocol || location.host !== $a.host
location.protocol !== $a.protocol || location.host !== $a.host $a = null
} catch (err) {} } catch (err) {}
if (crossDomain && options.credentials === 'omit') { if (crossDomain && options.credentials === 'omit') {
@ -149,10 +155,6 @@ class _Request {
if (params) { if (params) {
options.url += (~options.url.indexOf('?') ? '&' : '?') + params options.url += (~options.url.indexOf('?') ? '&' : '?') + params
} }
if (options.cache === 'no-store') {
options.url +=
(~options.url.indexOf('?') ? '&' : '?') + '_t_=' + Date.now()
}
} else { } else {
if (!hasAttach) { if (!hasAttach) {
if (~options.headers['content-type'].indexOf('json')) { if (~options.headers['content-type'].indexOf('json')) {
@ -176,18 +178,17 @@ class _Request {
var url = options.url var url = options.url
delete options.url delete options.url
for (let k in options) { for (let k in options) {
if ( if (options[k] === null || options[k] === undefined || options[k] === '') {
options[k] === null ||
options[k] === undefined ||
options[k] === ''
) {
delete options[k] delete options[k]
} }
} }
return NATIVE_FETCH(url, options) return nativeFetch(url, options)
.then(r => { .then(r => {
clearTimeout(this.timer) clearTimeout(this.timer)
var isSucc = r.status >= 200 && r.status < 400 let isSucc = r.status >= 200 && r.status < 400
if (this._owner._inject_res) {
r = this._owner._inject_res(r)
}
if (isSucc) { if (isSucc) {
return r return r
} else { } else {
@ -209,17 +210,36 @@ class _Request {
} }
} }
const _fetch = function(url, options) { const _fetch = function (url, options) {
return new _Request(url, options, { return new _Request(
url,
options,
{
BASE_URL: _fetch.BASE_URL, BASE_URL: _fetch.BASE_URL,
__INIT__: _fetch.__INIT__ || Object.create(null) __INIT__: _fetch.__INIT__ || Object.create(null)
}) },
_fetch
)
} }
function inject(target) {
_fetch.create = function(BASE_URL, __INIT__ = Object.create(null)) { target.inject = {
return function(url, options) { request(callback) {
return new _Request(url, options, { BASE_URL, __INIT__ }) target._inject_req = callback
},
response(callback) {
target._inject_res = callback
}
} }
} }
_fetch.create = function (BASE_URL, __INIT__ = Object.create(null)) {
var another = function (url, options) {
return new _Request(url, options, { BASE_URL, __INIT__ }, another)
}
inject(another)
return another
}
inject(_fetch)
export default _fetch export default _fetch