javascript 異步請求封裝成同步請求

 

        此方法是異步請求封裝成同步請求,加上token驗證,環境試用微信小程序,能夠修改文件中的ajax,進行封裝本身的,好比用axios等ios

       成功碼採用標準的 200 到 300 和304 ,須要能夠自行修改ajax

       同步任務接入以後,每一個任務會進行token的驗證,每一個任務之間都是同步請求,包括tokenjson

/**
 *  同步流請求
 *  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

 

    引入方式,全局調用axios

import Http from './public/js/request'
wx.http = Http

 

    調用執行,可用bind函數進行傳參小程序

    success返回爲成功的,code值流入任務進行code值判斷區分 resolve微信小程序

    fail返回失敗 rejectpromise

    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 }) } }) }) } })
相關文章
相關標籤/搜索