javascript 异步请求封装成同步请求
此方法是异步请求封装成同步请求,加上token验证,环境试用微信小程序,可以修改文件中的ajax,进行封装自己的,比如用axios等
成功码采用标准的 200 到 300 和304 ,需要可以自行修改
同步任务接入之后,每个任务会进行token的验证,每个任务之间都是同步请求,包括token
/** * 同步流请求 * token验证每个接口 * 柯里化添加同步任务 * resolve返回res,cb * reject 返回res,cb * 通过任务中断测试 * 通过成功失败回调函数测试 * * 任务流 任务接入柯里化函数 currying(()=>{}) --> * 开始执行 currying() 进入g函数循环同步执行异步方法 --> * 执行异步方法 调用 rp 函数 封装 return new promise --> * rp 函数 执行判断 token 状态 进行处理 */ const regeneratorRuntime = require('./regenerator-runtime/runtime.js') //runtime类 const errorMessage = '服务繁忙,稍后再试' //公共提示 const successMessage = '完成' //公共提示 class SuperClass { constructor() { Object.assign(this, {}) //等待执行的接口 this.wait = [] } //Promise 请求接口 rp(opts, skipToken = false) { const _t = this, data = opts.data || {} //小程序标识 data.source = opts.sourceFlag ? data.source : 1; //请求信息 console.group(`请求接口---${opts.url}`); console.log('接口信息', { opts, skipToken }) console.groupEnd(); return new Promise(function(resolve, reject) { opts.header = { "Content-Type": "application/json;charset=utf-8", //不需要走token的接口 Authorization: !!opts.skipToken ? '' : (wx.getStorageSync('token') || '') } wx.request({ url: '域名' + opts.url, data: data, header: opts.header, method: opts.method, dataType: 'json', responseType: 'text', success: function(res) { const { data } = res //成功 400为token失效 处理token失效问题 内层函数收集token失败码归并处理 if (data && (_t.successCode({ code: data.code }) || data.code == 400)) { resolve(data) } else { //其他不可预测为失败 reject(data) } }, fail: function(res) { reject(res.data) }, complete: function(res) { //完成停止加载 wx.hideToast() opts.complete && opts.complete(res.data) } }) }) } //为空参数抛异常 paramNoNull() { throw new Error('Missing parameter') } // g函数 async g() { let _t = this, //中断任务 isbreak = !1 for (let [i, v] of _t.wait.entries()) { const r = await v().catch((res) => { //收集 所有的错误 统一执行 提示 或者错误回调 const { cb, message } = res //同步流中断 _t.clearWait() isbreak = !0; //没有回调函数执行错误提示 'cb' in res ? cb() : (wx.factory._toast(message || errorMessage)) }) //任务执行成功 if (!!r && r.constructor === Object && !!Object.keys(r).length) { const { res: { code, data, message }, cb } = r //外层函数只处理成功状态 if (_t.successCode({ code })) { !!cb && cb() //同步流执行完成 if ((i + 1) == _t.wait.length) { _t.clearWait() wx.factory._toast(message || successMessage) } } else { //同步流中断 _t.clearWait() isbreak = !0 wx.factory._toast(message || errorMessage) } } if (!!isbreak) { break } } } //清空任务 clearWait() { this.wait = [] } //柯里化 currying() { const _t = this return (function(arg) { if (arg.length === 0) { _t.g() } else { [].push.apply(_t.wait, arg); } })(arguments) } //成功码 successCode({ code = 404 }) { return (code >= 200 && code < 300) || code == 304 } } //超类,实现多继承 const decorator = Sup => class extends Sup { constructor(...args) { super(...args) } //获取token接口 greatetoken(opts) { let codeOPts = JSON.parse(JSON.stringify(opts)); codeOPts.url = `/getToken` codeOPts.method = `POST` codeOPts.data = { appIds: "xx", userId: 5 } return super.rp(codeOPts, true).then((res) => { const { code, data } = res if (super.successCode({ code: cb.code })) { if (!!data && !!data.token) { //全局token存储 方式为 storage wx.setStorageSync('token', data.token) } else { wx.factory._toast('获取token失败') } } else { wx.factory._toast('获取token失败') } }).catch(() => { wx.factory._toast('获取token失败') }) } /** * 接口公共类 * 同步请求返回 Promise * 请求 token 为前提,为空 过期重新请求 */ async send(opts) { const token = wx.getStorageSync('token'), sendFun = (opts) => { //转化http请求 catch捕获promise的reject 展示接口级别错误 只做console打印 其他操作流入g函数(回调,提示) return super.rp(opts).catch(res => { //此处显示rp reject 报错 console.group(`%c请求接口---${opts.url}---报错`, 'color:red;'); console.log(` --> 参数`, { data: opts.data }); console.log(` --> 返回值`, { res }); console.groupEnd(); //把错误信息传到 g 函数的catch里面 opts.fail && opts.fail(res) }) }, successFun = async(opts) => { const cb = await sendFun(opts) //把成功信息传到g函数里面 super.successCode({ code: cb.code }) && opts.success && opts.success(cb) } if (!opts.skipToken) { //需要token请求 if (!token) { //token为空 直接发起token请求 await this.greatetoken(opts) await successFun(opts) } else { const cb = await sendFun(opts) if (!!cb) { //400 token过期 只有在存在token的情况下才会有时效的情况 归并处理 if (cb.code == 400) { await this.greatetoken(opts) await successFun(opts) } else { //把成功信息传到g函数里面 super.successCode({ code: cb.code }) && opts.success && opts.success(cb) } } } } else { await successFun(opts) } } post(opts) { opts.method = "POST"; this.send(opts) } get(opts) { opts.method = "GET"; this.send(opts); } } class Http extends decorator(SuperClass) { //子类 constructor() { //继承参数 super() } } export default new Http
引入方式,全局调用
import Http from './public/js/request'
wx.http = Http
调用执行,可用bind函数进行传参
success返回为成功的,code值流入任务进行code值判断区分 resolve
fail返回失败 reject
complete执行的为方法
Page({ onLoad(){ wx.http.currying(this.a.bind(this, { a: 1 })) //进行传参bind wx.http.currying(this.b) wx.http.currying() }, a() { const _t = this wx.factory._toast('加载a信息中...', 6000) return new Promise((resolve, reject) => { wx.http.post({ url: 'a', data: { "params": { id:33 } }, success(res) { resolve({ res,
cb()=>{} }) }, fail(res) { reject({ res,
cb()=>{} }) } }) }) }, b() { const _t = this wx.factory._toast('加载b信息中...', 6000) return new Promise((resolve, reject) => { wx.http.post({ url: 'b', data: { id:33 }, success(res) { resolve({ res }) }, fail(res) { reject({ res }) } }) }) } })