xe-ajax 基于 Promise API 的异步请求函数

最新版本见 Github,点击查看历史版本

API

提供三种常用的便捷函数

  • doAll ( iterable )
  • ajax ( options )
  • ~
  • fetch ( url,options )
  • fetchHead ( url,options )
  • fetchDelete ( url,options )
  • fetchJsonp ( url,params,options )
  • fetchGet ( url,options )
  • fetchPost ( url,body,options )
  • fetchPut ( url,options )
  • fetchPatch ( url,options )
  • ~
  • doHead ( url,options )
  • doDelete ( url,options )
  • doJsonp ( url,options )
  • doGet ( url,options )
  • doPost ( url,options )
  • doPut ( url,options )
  • doPatch ( url,options )
  • ~
  • headJSON ( url,options )
  • deleteJSON ( url,options )
  • jsonp ( url,options )
  • getJSON ( url,options )
  • postJSON ( url,options )
  • putJSON ( url,options )
  • patchJSON ( url,options )

入参

  • url(字符串) 请求地址,可被自定义 options 属性覆盖
  • params/body(可选,对象/数组) 要发送的数据,可被自定义 options 属性覆盖
  • options (可选,对象) 参数

options 参数

*: 只支持最高版本的浏览器。

参数 类型 描述 默认值
url String 请求地址
baseURL String 基础路径 默认上下文路径
method String 请求方法 'GET'
params Object/Array 请求参数
body Object/Array 提交参数
bodyType String 提交参数方式,可以设置json-data,form-data 'json-data'
mode String 请求的模式,可以设置cors,no-cors,same-origin 'cors'
cache String 处理缓存方式,可以设置default,no-store,no-cache,reload,force-cache,only-if-cached 'default'
credentials String 设置 cookie 是否随请求一起发送,可以设置: omit,same-origin,include 'same-origin'
* redirect String 重定向模式,可以设置follow,error,manual 'follow'
* referrer String 可以设置no-referrer,client或URL 'client'
* referrerPolicy String 可以设置: no-referrer,no-referrer-when-downgrade,origin,origin-when-cross-origin,unsafe-url
* keepalive String 选项可用于允许请求超过页面的生存时间
* integrity String 包括请求的subresource integrity值
jsonp String jsonp入参属性名 'callback'
jsonpCallback String jsonp响应结果的回调函数名 默认自动生成函数名
timeout Number 设置超时
headers Object 请求头
transformParams Function (params,request) 用于改变URL参数
paramsSerializer Function (params,request) 自定义URL序列化函数
transformBody Function (body,request) 用于改变提交数据
stringifyBody Function (body,request) 自定义转换提交数据的函数
validateStatus Function (response) 自定义校验请求是否成功 response.status >= 200 && response.status < 300

Headers

属性 类型 描述
set Function (name,value) 添加
append Function (name,value) 追加
get Function (name) 根据 name 获取
has Function (name) 检查 name 是否存在
delete Function (name) 根据 name 删除
keys Function 以迭代器的形式返回所有 name
values Function 以迭代器的形式返回所有 value
entries Function 以迭代器的形式返回所有 [name,value]
forEach Function (callback,context) 迭代器

Response

属性 类型 描述
body ReadableStream 数据流
bodyUsed Boolean 内容是否已被读取
headers Headers 响应头
status Number 状态码
statusText String 状态信息
url String 返回请求路径
ok Boolean 请求完成还是失败
redirected Boolean 是否重定向了
type String 类型
clone Function 返回一个新的 Response 对象
json Function 获取 json 数据
test Function 获取 text 数据
blob Function 获取 Blob 对象
arrayBuffer Function 获取 ArrayBuffer 对象
formData Function 获取 FormData 对象

全局参数设置

import XEAjax from 'xe-ajax'

XEAjax.setup({
  baseURL: 'http://xuliangzhan.com',bodyType: 'json-data',credentials: 'include',log: false,headers: {
    'Accept': 'application/json,text/plain,\*/\*;'
  },validateStatus (response) {
    // 如何需要实现复杂的场景判断,请使用拦截器
    return response.status >= 200 && response.status < 300
  },transformParams (params,request) {
    // 用于在请求发送之前改变URL参数
    if (request.method === 'GET') {
      params.queryDate = params.queryDate.getTime()
    }
    return params
  },paramsSerializer (params,request) {
    // 自定义URL序列化函数,最终拼接在url
    return XEUtils.serialize(params)
  },
  transformBody (body,request) {
    // 用于在请求发送之前改变提交数据
    body.startTime = body.startDate.getTime()
    return body
  },stringifyBody (body,request) {
    // 自定义格式化提交数据函数
    return JSON.stringify(body)
  }
})

示例

基本使用

const XEAjax = require('xe-ajax')

XEAjax.ajax({
  url: '/api/user/list',method: 'GET',params: {
    id: 1
  }
})
  .then(response => {
    if (response.ok) {
      // 请求成功
    } else {
      // 请求失败
    }
  })
  .catch(e => {
    // 发生错误
    console.log(e.message)
  })

fetch 调用,返回一个结果为 Response 对象的 Promise

import XEAjax from 'xe-ajax'

XEAjax.fetch('/api/user/list',{
  method: 'POST',body: {
    name: 'test'
  }
})
  .then(response => {
    if (response.ok) {
      // 请求成功
    } else {
      // 请求失败
    }
  }).catch(e => {
    // 发生错误
    console.log(e.message)
  })

// Response Text
XEAjax.fetch('/api/user/list')
  .then(response => {
    response.text().then(text => {
      // text
    })
  })

// Response JSON
XEAjax.fetch('/api/user/list')
  .then(response => {
    response.json().then(data => {
      // data
    })
  })

// Response Blob
XEAjax.fetch('/api/user/list')
  .then(response => {
    response.blob().then(blob => {
      // blob
    })
  })

// Response ArrayBuffer
XEAjax.fetch('/api/user/list')
  .then(response => {
    response.arrayBuffer().then(arrayBuffer => {
      // arrayBuffer
    })
  })

// Response FormData
XEAjax.fetch('/api/user/list')
  .then(response => {
    response.formData().then(formData => {
      // formData
    })
  })

// 使用 application/json 方式提交,默认使用 JSON.stringify 序列化数据
let body1 = {
  name: 'u111',password: '123456'
}
XEAjax.fetchPost('/api/user/save',body1,{bodyType: 'json-data'})

// 使用 application/x-www-form-urlencoded 方式提交,默认使用 XEAjax.serialize 序列化数据
let body2 = {
  name: 'u222',body2,{bodyType: 'form-data'})

// 模拟表单 multipart/form-data 提交
let file = document.querySelector('#myFile').files[0]
let formBody = new FormData()
formBody.append('file',file)
XEAjax.fetchPost('/api/user/save',formBody)

// 查询参数和数据同时提交
XEAjax.fetchPost('/api/user/save',{name: 'u333',password: '123456'},{params: {id: 111}})

XEAjax.fetchGet('/api/user/list')
XEAjax.fetchPut('/api/user/update',{name: 'u222'})
XEAjax.fetchDelete('/api/user/delete/111')

根据请求状态码(成功或失败),返回结果为 Response 数据的 Peomise 对象 (v3.4.0+)

import XEAjax from 'xe-ajax'

// 对请求的响应包含以下信息
// result => {data,status,statusText,headers}

// 根据 validateStatus 状态校验判断完成还是失败
XEAjax.doGet('/api/user/list').then(result => {
  // 请求成功 result.data
}).catch(result => {
  // 请求失败
})

XEAjax.doGet('/api/user/list/15/1')
XEAjax.doPost('/api/user/save',{name: 'u111'})
XEAjax.doPut('/api/user/update',{name: 'u222'})
XEAjax.doDelete('/api/user/delete/111')

根据请求状态码(成功或失败),返回结果为 json 数据的 Peomise 对象

import XEAjax from 'xe-ajax'

// 根据 validateStatus 状态校验判断完成还是失败,直接可以获取响应结果
XEAjax.getJSON('/api/user/list').then(data => {
  // 请求成功 data
}).catch(data => {
  // 请求失败
})

XEAjax.getJSON('/api/user/list/15/1')
XEAjax.postJSON('/api/user/save',{name: 'u111'})
XEAjax.putJSON('/api/user/update',{name: 'u222'})
XEAjax.deleteJSON('/api/user/delete/111')

jsonp 调用

import XEAjax from 'xe-ajax'

// 例子1
// 请求路径: http://xuliangzhan.com/api/jsonp/public/message?callback=jsonp_xeajax_1521272815608_1
// 服务端返回结果: jsonp_xeajax_1521272815608_1({message: 'success'})
XEAjax.fetchJsonp('http://xuliangzhan.com/api/jsonp/public/message')
  .then(response => {
    if (response.ok) {
      response.json().then(data => {
        // data
      })
    }
  })

// 例子2
// 请求路径: http://xuliangzhan.com/api/jsonp/public/message?cb=jsonp_xeajax_1521272815608_2
// 服务端返回结果: jsonp_xeajax_1521272815608_2({message: 'success'})
XEAjax.doJsonp('http://xuliangzhan.com/api/jsonp/public/message',null,{jsonp: 'cb'})
  .then(response => {
    // response.data
  })

// 例子3
// 请求路径: http://xuliangzhan.com/api/jsonp/public/message?id=222&cb=func
// 服务端返回结果: func({message: 'success'})
XEAjax.jsonp('http://xuliangzhan.com/api/jsonp/public/message',{id: 222},{jsonp: 'cb',jsonpCallback: 'func'})
  .then(data => {
    // data
  })

并发多个请求

import XEAjax from 'xe-ajax'

let iterable1 = []
iterable1.push(XEAjax.fetchGet('/api/user/list'))
iterable1.push(XEAjax.doGet('/api/user/list'))
iterable1.push(XEAjax.postJSON('/api/user/save'),{name: 'n1'})
Promise.all(iterable1).then(datas => {
  // 所有异步完成之后执行
}).catch(e => {
  // 请求失败时执行
})

// doAll 使用对象参数,用法和 Promise.all 一致
let iterable2 = []
iterable2.push({url: '/api/user/list'})
iterable2.push({url: '/api/user/save',body: {name: 'n1'}},method: 'POST'})
XEAjax.doAll(iterable2)

嵌套请求

import { fetchGet,doGet,getJSON } from 'xe-ajax'

// 相互依赖的嵌套请求
fetchGet('/api/user/info')
  .then(response => response.json())
  .then(data => fetchGet('/api/user/details',{id: data.id}))
  .then(response => {
    if (response.ok) {
      response.json().then(data => {
        // data
      })
    }
  })
doGet('/api/user/info')
  .then(result => doGet('/api/user/details',{id: result.data.id}))
  .then(result => {
    // result.data
  })
getJSON('/api/user/info')
  .then(data => getJSON('/api/user/details',{id: data.id}))
  .then(data => {
    // data
  })

上传/下载 (v3.4.9+)

参数

属性 类型 描述
onUploadProgress Function (event) 上传进度监听
onDownloadProgress Function (event) 下载进度监听
meanSpeed Number 默认0关闭,设置速率为均衡模式,每隔多少毫秒内计算平均速率
fixed Number 默认2位数

Progress 对象

属性 类型 描述
autoCompute Boolean 是否自动计算进度,默认true
value Number 当前进度 %
loaded Object 已传输大小 {value: 原始大小B,size: 转换后大小,unit: 转换后单位}
total Object 总大小 {value: 原始大小B,unit: 转换后单位}
speed Object 传输速度/秒 {value: 原始大小B,unit: 转换后单位}
remaining Number 剩余时间/秒
time Number 时间戳
import XEAjax from 'xe-ajax'

// 上传、下载
var file = document.querySelector('#myFile').files[0]
var formBody = new FormData()
formBody.append('file',file)
XEAjax.fetchPost('/api/upload',formBody)
XEAjax.doPost('/api/upload',formBody)
XEAjax.postJSON('/api/upload',formBody)


// 上传进度
// 创建一个进度监听对象
let progress = new XEAjax.Progress()
// 监听上传进度
progress.onUploadProgress = evnt => {
  console.log(`进度:${progress.value}% ${progress.loaded.size}${progress.loaded.unit}${progress.total.size}/${progress.total.unit}; 速度:${progress.speed.size}/${progress.speed.unit}秒; 剩余:${progress.remaining}秒`)
}
var file = document.querySelector('#myFile').files[0]
var formBody = new FormData()
formBody.append('file',formBody,{progress})
// 进度:1% 176KB/14.26MB; 速度:1.69MB/秒; 剩余:8秒
// 进度:3% 368KB/14.26MB; 速度:640KB/秒; 剩余:22秒
// 进度:8% 1.16MB/14.26MB; 速度:1.56MB/秒; 剩余:8秒
// ...
// 进度:99% 14.08MB/14.26MB; 速度:119.6KB/秒; 剩余:2秒
// 进度:100% 14.26MB/14.26MB; 速度:114.4KB/秒; 剩余:0秒


// 下载进度
// 创建一个进度监听对象
let progress = new XEAjax.Progress()
// 监听下载进度
progress.onDownloadProgress = evnt => {
  console.log(`进度:${progress.value}% ${progress.loaded.size}${progress.loaded.unit}${progress.total.size}/${progress.total.unit}; 速度:${progress.speed.size}/${progress.speed.unit}秒; 剩余:${progress.remaining}秒`)
}
XEAjax.fetchGet('/api/download/file/1',{progress,method: 'GET'})

取消请求 (v3.2.0+)

AbortController 控制器对象

允许控制一个或多个取消指令请求

import XEAjax from 'xe-ajax'

// 创建一个控制器对象
// 如果当前环境支持 AbortController,则使用原生的 AbortController
let controller = new XEAjax.AbortController()
// let controller = new AbortController() // 或者使用原生
// 获取signal
let signal = controller.signal
// 给请求加入控制器 signal
XEAjax.fetchGet('/api/user/list',{id: 1},{signal})
  .then(response => {
    // 请求成功
  }).catch(e => {
    // 请求被取消
  })
setTimeout(() => {
  // 终止请求
  controller.abort()
},50)

拦截器 (v3.0+)

拦截器可以对请求之前和请求之后的任何参数以及数据做处理,注意要调用next执行下一步,否则将停止执行。

Request 拦截器

XEAjax.interceptors.request.use(Function([request,next]))

import XEAjax from 'xe-ajax'

// 请求之前拦截器
XEAjax.interceptors.request.use((request,next) => {
  // 用于请求的权限拦截、设置请求头、Token 验证、参数等处理...

  // 设置参数
  request.params.version = 1
  // 设置 Token 验证,预防 XSRF/CSRF 攻击
  request.headers.set('X-Token',cookie('x-id'))

  // 调用 next(),继续执行下一个拦截器
  next()
})

Response 拦截器

XEAjax.interceptors.response.use(Function([response,next,request]),Function([response,next]))

import XEAjax from 'xe-ajax'

// 请求完成之后拦截
XEAjax.interceptors.response.use((response,next) => {
  // 请求完成之后统一处理,例如校验登录是否失效、消息提示,特殊场景处理等...

  // 例子: 判断登录失效跳转
  if (response.status === 403) {
    router.replace({path: '/login'})
  } else {
    // 调用 next(),继续执行下一个拦截器
    next()
  }
},(e,next) => {
  // 请求发生错误
  // 调用 next(),继续执行下一个拦截器
  next()
})

// 请求完成之后重置响应数据
XEAjax.interceptors.response.use((response,next) => {
  // 对所有请求返回统一的数据结构
  // 格式: {status: 200,statusText: 'OK',body: {},headers: {}}

  // 例如,对所有请求结果进行处理,返回统一的结构
  response.json().then(data => {
    let body = {
      status: response.status === 200 ? 'success' : 'error',result: data
    }
    // 重置响应数据并继续执行下一个拦截器
    next({status: response.status,body: body})
  })
},next) => {
  // 对所有请求错误返回统一的数据结构
  let body = {
    message: 'error',result: null
  }
  // 重置响应数据并继续执行下一个拦截器
  next({status: 200,body: body})
})

混合函数

./ajax.js

import XEAjax from 'xe-ajax'

export function fn1 () {}
export function fn2 () {}
// ...

./main.js

import XEAjax from 'xe-ajax'
import ajaxFns from './ajax'

XEAjax.mixin(ajaxFns)

XEAjax.fn1()
XEAjax.fn2()

相关文章

$.AJAX()方法中的PROCESSDATA参数 在使用jQuery的$.ajax()方...
form表单提交的几种方式 表单提交方式一:直接利用form表单提...
文章浏览阅读1.3k次。AJAX的无刷新机制使得在注册系统中对于...
文章浏览阅读1.2k次。 本文将解释如何使用AJAX和JSON分析器在...
文章浏览阅读2.2k次。/************************** 创建XML...
文章浏览阅读3.7k次。在ajax应用中,通常一个页面要同时发送...