我曾寫過兩篇文章:jQuery進階:用最優雅的方式寫ajax請求, axios進階:用最優雅的方式寫ajax請求, 原理都是在將使用配置檔案的方式,自動生成介面方法。 在多個專案中,我曾使用這種配置的方式批量生成ajax介面,但是每次都要造輪子是很繁瑣的,索性自己釋出一個npm包吧,於是xfire出來了。
將配置資料從程式碼中分離出來 -- 《編寫可維護的JavaScript》--Nicholas C. Zakas,我是看了這本書,才激發出用配置檔案生成各種介面的想法。
xfire地址:點選到達
覺得不錯的話,可以給xfire點個贊或者開個issue,或者提個建議。謝謝。
xfire
非常簡單,高度可配置的fetch介面批量生成工具。
特點
非常簡單: 提供配置檔案,自動生成介面
提前驗證:支援請求體格式驗證
報錯詳細: 給出具體的報錯位置,欄位資訊
安裝
npm install -S xfire
yarn add xfire
複製程式碼
demo
首先需要一個配置檔案
// api.config.js
export default {
prefix: 'http://localhost:80',
list: [
{
name: 'login',
desp: 'sercurity login',
path: '/agent/login',
method: 'post',
contentType: 'formData',
bodyStruct: {
username: 'string',
password: 'string',
namespace: 'string'
},
defaultBody: {
password: 'Aa123456'
},
status: {
401: 'username or password wrong'
}
},
{
name: 'heartBeat',
path: '/sdk/api/csta/agent/heartbeat/{{agentId}}',
},
{
name: 'setAgentState',
desp: 'set agent state',
path: '/sdk/api/csta/agent/state/{{namespace}}',
method: 'post',
bodyStruct: {
agentId: 'string?',
loginId: 'string',
func: 'string',
agentMode: 'string?',
device: 'string?',
password: 'string'
}
}
]
}
複製程式碼
然後引入xfire
import xfire from 'xfire'
import apiConfig from './api.config.js'
const API = xfire.init(apiConfig)
複製程式碼
POTS 傳送formData型別的資料示例
API.login.fire({}, {
username: 'wangduanduan',
password: '123456',
namespace: 'dd.com'
})
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
複製程式碼
GET 資料示例
API.heartBeat.fire({
agentId: '5001@dd.com'
})
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
複製程式碼
POST json型別資料示例
API.setAgentState.fire({
namespace: 'windows'
}, {
agentId: '5001@dd.com',
loginId: '5001@dd.com',
func: 'login',
agentMode: 'Ready',
device: '8001@dd.com',
password: '123456'
})
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
複製程式碼
xfire API
const API = xfire.init(config)
複製程式碼
config 欄位說明
注意:如果config無法通過下面的格式驗證,則會直接報錯
欄位名 | 型別 | 是否必須 | 預設值 | 說明 |
---|---|---|---|---|
config.prefix | string | 是 | 無 | 介面url公用的字首 |
config.list | array | 是 | 無 | 介面陣列 |
config list欄位說明
欄位名 | 型別 | 是否必須 | 預設值 | 說明 |
---|---|---|---|---|
name |
string | 是 |
無 | 介面名 |
desp | string | 否 | 無 | 介面描述 |
path |
string | 是 |
無 | 介面路徑 |
method | enum string | 否 | get | 請求方式: get, post, put, delete |
contentType | enum string | 否 | json | 請求體型別: json, formData。json會被渲染: application/json; charset=UTF-8, formData會被渲染成: application/x-www-form-urlencoded; charset=UTF-8 |
bodyStruct | object | 否 | 無 | 請求體格式驗證結構, 如果bodyStruct存在,則使用bodyStruct驗證body: 具體格式參考superstruct |
defaultBody | object | 否 | 無 | 預設請求體。bodyStruct存在的情況下才有效 |
status | object | 否 | 無 | 響應狀態碼及其含義 |
當某個list物件的 name 不存在時,config驗證時的報錯:
Uncaught StructError: Expected a value of type `string` for `name` but received `undefined`.
複製程式碼
當傳送請求時,請求體不符合bodyStruct時, 報錯如下
...
name: 'login',
desp: 'sercurity login',
path: '/agent/login',
method: 'post',
contentType: 'formData',
bodyStruct: {
username: 'string',
password: 'string',
namespace: 'string'
},
...
API.login.fire({}, {
// username: '5001',
password: 'Aa123456',
namespace: 'zhen04.cc'
})
Uncaught StructError: Expected a value of type `string` for `username` but received `undefined`.
複製程式碼
xfire 例項 API
xfire.init()方法會返回xfire例項物件,該物件上有一個特殊方法$setHeaders
, 還有其他的由配置檔案產生的方法。
const API = xfire.init(apiConfig)
複製程式碼
$setHeaders(): 設定請求頭部資訊
$setHeaders()用來設定除了contentType
以外的請求頭, 一旦設定請求頭部資訊,所有的例項介面在傳送請求時,都會帶有該頭部資訊。
API.$setHeaders({sessionId: 'jfsldkf-sdflskdjf-sflskfjlsf'})
複製程式碼
api方法: fire(pathParm, body)
pathParm物件上的資料最終會被渲染到請求路徑上
, body是請求體。
...
{
name: 'heartBeat',
desp: 'agent heart beat',
path: '/sdk/api/csta/agent/heartbeat/{{agentId}}',
method: 'post'
},
...
複製程式碼
類似上面的物件,會產生一個以heartBeat
為名稱的方法,所有請求方法都是fire()方法。
API.xxx.fire(pathParm, body)
// 不需要請求體時, body可以不傳
API.xxx.fire(pathParm)
// 不需要引數渲染到路徑時,pathParm必須傳空物件:{}
API.xxx.fire({}, body)
複製程式碼
例子:
API.heartBeat({
agentId: '5001@ee.com'
})
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
複製程式碼
關於path
和 fire的 pathParm
引數:
// path 如下
path: '/store/order/{{type}}/{{age}}'
// 則pathParm應該是
{
type: 'dog',
age: 14
}
複製程式碼
注意
: pathParm不支援複雜的資料型別。
// 原始資料型別 string, number, boolean 都是可以的
{
key1: 'string',
key2: number,
key3: boolean
}
// 複雜的資料型別,如陣列和巢狀物件, 函式, 將導致渲染失敗
// bad
{
key1: [1, 3, 3],
key2: {
key3: 'string'
},
key4: function(){}
}
複製程式碼
polyfill
xfire底層使用了瀏覽器原生的Promise
, fetch
, Object.keys()
, Object.assign()
所以對瀏覽器是有要求的。xfire本身不帶有任何polyfill。
目前IE11以及以下是不支援Promise和fetch的。
在此給出兩個方案:
方案1: babel-polyfill
通過引入babel-polyfill, 讓瀏覽器支援xfire所需要的原生方法。
方案2: polyfill.io
只需要為您的網站,為每個瀏覽器量身定製的polyfills。 複製程式碼釋放魔法:
<script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
複製程式碼
Polyfill.io讀取每個請求的User-Agent頭並返回適合請求瀏覽器的polyfill。 根據您在應用中使用的功能量身定製響應,並檢視我們的例項以快速入門。
ajax Vs fetch
與其使用各種ajax第三方庫,不如使用原始fetch。ajax是過去,fetch是現在和將來。
總結一下,Fetch 優點主要有:
語法簡潔,更加語義化 基於標準 Promise 實現,支援 async/await 同構方便,使用 isomorphic-fetch --傳統 Ajax 已死,Fetch 永生 未來更容易擴充套件 -- by me
我使用ajax經歷過三個階段:
- jQuery時期,我用jQuery的
ajax
- 類似Vue的現代框架時,使用axio
- 再後來我就使用瀏覽器原生的
fetch
Fetch API 提供了一個 JavaScript介面,用於訪問和操縱HTTP管道的部分,例如請求和響應。它還提供了一個全域性 fetch()方法,該方法提供了一種簡單,合乎邏輯的方式來跨網路非同步獲取資源。-- MDN
這種功能以前是使用 XMLHttpRequest實現的。Fetch提供了一個更好的替代方法,可以很容易地被其他技術使用,例如 Service Workers。Fetch還提供了單個邏輯位置來定義其他HTTP相關概念,例如 CORS和HTTP的擴充套件。-- MDN
從caniuse的資料來看,fetch方法除IE11不支援以外,大部分常用瀏覽器都支援了。
fetch介面示例:
fetch('/users.json')
.then(function(response) {
return response.json()
}).then(function(json) {
console.log('parsed json', json)
}).catch(function(ex) {
console.log('parsing failed', ex)
})
fetch('/users.html')
.then(function(response) {
return response.text()
}).then(function(body) {
document.body.innerHTML = body
})
複製程式碼
fetch相關文章
fetch相關庫
進階書籍
ie 8/9/10 早已被微軟放棄
微軟公司正式宣佈:從當地時間2016年1月12日,停止對IE 8/9/10三個版本的技術支援,相應的使用者將不會再收到任何來自微軟官方的IE安全更新。-- Support for older versions of Internet Explorer ended