next-api v2.0.4
next-api
一个通用的API客户端,通过简单的配置可以让很方便地提交ajax请求。
使用异步函数,使得API调用变得方便,可读性大幅提高
更新动态
2017年08月21日18:24:25
- 修正.d.ts中的部分定義錯誤
2017年08月19日21:02:12
- 增加文件上传进度支持,参见文件上传进度显示
- 修复fetchAPI中跨域请求默认值问题(不小心将cors写成cros)
- 整个项目重新使用typescript实现
2017年08月13日01:31:43
- 增加base64文件上传,参见base64文件上传方式
- api增加typescript支持,参见typescript中的API定义
安装和配置
npm install --save next-api
安装完成后其实已经可以使用了。 不过为了更加方便的使用,最好先进行一些配置
下面是一个配置的示例:
let {api, config, apiType} = require('next-api');
//配置服务器响应数据类型,这里配置的是json
config.apiType = apiType.json
//配置API基地址,配置之后以后写url的时候,可以不用写前面的部分
config.baseUrl = 'http://localhost:3000/api/'
//配置fetch选项,fetch选项的具体内容请参考 fetch api 相关类容
//这里假设在FetchAPI的header中添加一个token
config.fetchOption = {
headers:{
token:'xxxxxxxxx'
}
}
//接收到数据时的数据处理配置,
//可以将接收到的数据进行转换,并返回一个新的数据,
//同时还可以在这个函数中抛出异常,所抛出的异常会在FetchAPI的catch中捕获
//这个函数返回的数据也就是API调用的结果(在下一节会介绍)。
config.onData = data=>{
//如果服务器返回了错误则抛出异常
if(data.error) throw new Error(data.error)
//否则将服务器得到的数据取出来
return data.data;
}
//错误处理配置
//当发生错误时会调用此函数。
//此函数接受一个Error对象和当前状态码(可能没有状态码),并返回一个新的Error对象
//错误的来源可能有:服务器关闭,服务器返回了其他状态码,API返回的错误(该错误有onData函数处理并抛出),以及其他用户代码中的错误
//这个函数必须返回一个Error对象,否则API调用时捕获到的错误可能不好处理。
config.onError = (err, status)=>{
//服务器返回403,跳转到登录
if(status && status==403){
window.location.href = '/login'
return new Error('身份过期,正在跳转到登录页面')
}else{
return err;
}
}
如何使用
使用API分成两步,API的定义和API的调用,
目前此api接口的请求方式有5种:get、post、put、del(delete)、pacth,通过api.xxx来生成对应请求方式的API。
一般来说,将API的定义统一放在一个文件中,方便调用。
假如说有两组API:用户API和分组API,用户API包括登录和修改个人信息, 分组API包括创建和删除分组。
那么可以有这样一个目录机构进行存放(当然也可以是其他的结构,按个人需求而定):
api (api目录)
| user.js (用户管理API)
| group.js (分组管理API)
那么user.js可以这么写(group.js就不做演示了)
//导入next-api的api对象,该对象用于创建api
let {api} = require('next-api')
//定义登录API,该api以get方式进行请求
//登录并返回用户信息
exports.login = api.get('/user/login')
//定义修改用户信息API,该API以post方式进行请求
//修改个人信息
exports.updateInfo = api.post('/user/info/update')
API定义完成后使用就非常简单了,下面给出一个简单的例子来演示用户登录:
let {login} = require('./api/user')
//假如用户点击登录按钮的时候调用这个函数
//这个函数必须是一个异步函数(前面有async),否则调用接口时只能使用then,而不能使用await。
//接收两个参数:账号和密码
async function handleLogin(number, passwd){
try{
//调用登录API得到用户信息,注意必须加上await关键字
let myInfo = await login({number, passwd})
console.log('登录成功,用户信息是', myInfo)
}catch(e){
console.log('登录失败,原因:' + e.message)
}
}
上面介绍的是异步函数的调用方法,使用这种可以让代码看起来更清晰明了。
但是如果你不想使用异步函数,怎么办呢?
因为api返回的结果是一个Promise对象,因此你可以用then和catch来进行处理。
上面例子的另一种写法:
let {login} = require('./api/user')
//假如用户点击登录按钮的时候调用这个函数
function handleLogin(number, passwd){
//调用登录API得到用户信息,注意必须加上await关键字
login({number, passwd})
//登录结果处理
.then(myInfo=>{
console.log('登录成功,用户信息是', myInfo)
})
//出错处理
.catch(e=>{
console.log('登录失败,原因:' + e.message)
})
}
除此之外,还可以通过引入script标签,例如
<!--导入next-api -->
<script src="js/next-api/dist/next-api.min.js"></script>
<!--一般来说需要进行配置 -->
<script>
//这里可以对next-api进行一些初始的配置操作
//包括设置header、设置跨域请求、服务器数据以及错误处理,等等。。。
</script>
<!--使用 -->
<script>
//定义登录接口
var login = nextApi.api.get('/user/login')
//调用登录接口
login({number:'admin', passwd:'admin'})
.then(function(myInfo){
console.log(myInfo)
})
.catch(function(e){
console.error(e)
})
</script>
base64文件上传方式
这里说明一下base64文件上传的使用方式。
base64文件上传使用的场景最常见的估计就是进行用户头像的设置了, 目前许多头像设置控件都是在浏览器端进行图片剪裁,得到一个base64的图片, 考虑到这个问题,增加了base64文件上传。
- 首先,需要构建一个Base64File对象,
- 然后,就没有然后了,直接像使用普通文件一样使用Base64File对象。
下面是一个示例:
import {Base64File, api} from 'next-api'
//太长,所以后面的省略了
let str = "data:image/jpeg;base64,/9j/4AAQSkZJRgAB..."
//先定义一个API
let uploadAvatar = api.post('/user/avatar')
//架设点击某个按钮调用这个函数进行设置头像
async handleSetAvatar(base64str){
//创建文件,第一个参数是base64字符串,第二个参数是文件名称,两个参数都是必须的
let file = new Base64File(base64str, 'avatar.png')
//提交头像
await uploadAvatar({avatar:file})
}
typescript中的API定义
相信很多人在使用typescript的时候都会感受到它的牛逼之处,所以我就不再多说了。
这里使用了typescript的泛型来定义API的参数和返回值, 可以在目前的绝大多数代码编辑器中实现代码提示。
接收两个类型,第一个是参数类型,第二个是返回值类型。
使用typescript可以这样定义API:
import {api} from 'next-api'
//定义用户登录API,
export userLogin = api.get<{
number:string, //账号参数
passwd:string //密码参数
tokenOnly?:boolean, //是否只获取token,可选参数
}, {
token:string, //获取到的token
userInfo?:{ //用户信息,可能会没有
id:number, //用户id
number:string, //用户账号
name:string, //用户姓名
//其他的就不写了
}
}>('/user/token')
这样定义之后,就能有很好的代码提示以及参数校验效果了。
文件上传进度使用说明
文件上传使用的是传统的XMLHttpRequest来实现的,以便于获取上传进度。
用法和之前的API基本一致,仅有一下几点不同
- config中的fetchOption无效,取而代之的是xhrOption,具体细节可以参考 index.d.ts中的定义
- 调用上传API时增加了两个参数,用于标识上传的文件以及进度的获取
简单用法:
import {upload} from 'next-api'
//创建API
let setAvatar = upload.post('/user/avatar')
//调用API
async function handleSetAvatar(user, inputDom){
//调用API设置头像,第2、3个参数可以不用传递
let result = await setAvatar({file:inputDom.files[0], user:user.id}, {
//这里可以是任意数据,这里设置的数据可以在上传列表中得到
//如果不设置数据,则上传列表中没有数据
fileName:inputDom.files[0].name
}, (loaded, total)=>{
//这里可以取得上传进度
console.log(`已上传${loaded}/${total}`)
})
//如果不适用第2、3个参数,则和之前的API没什么区别了
// let result = await setAvatar({file:inputDom.files[0], user:user.id})
console.log(result)
}
除此之外,文件上传API提供了一个上传列表,如果有需要,你可以方便地使用它。
简单用法如下:
import {upload} from 'next-api'
//假设这个dom用于展示上传列表
let fileUploadListDom = document.getElementById('file-upload-list')
//设置一个定时器,定期检测文件进度,并展示到界面上
setInterval(()=>{
let html = '<ul class="FileList">'
upload.list.forEach(item=>{
//这里的item.data就是上一个例子中API调用时设置的第二个参数的数据
html += `<li class="FileItem">
<div class="FileName">${ item.data.fileName }</div>
<div class="Persent">${ item.total ? parseInt ( item.loaded * 100 / item.total ) : 0 }%</div>
</li>`
})
html += '</ul>'
fileUploadListDom.innerHTML = html
}, 100)