luch
luch
  • 发布:2019-07-17 16:39
  • 更新:2024-02-21 21:17
  • 阅读:11656

#插件讨论# 【 仿axios封装request网络请求库,支持拦截器全局配置】issue 提交

分类:uni-app
2019-07-17 16:39 负责人:无 分享
已邀请:
今天你很美

今天你很美 - Stay hungry, stay foolish.

params参数传的对象中还挂有对象时 mergeUrl中addQueryString 组合的url有问题。 参考axios改了一下。
1、request.js

  static mergeUrl (url, baseUrl, params) {  
    const mergeUrl = Request.posUrl(url) ? url : `${baseUrl}${url}`  
    // if (Object.keys(params).length !== 0) {  
    //   const paramsH = Request.addQueryString(params)  
    //   mergeUrl += mergeUrl.includes('?') ? `&${paramsH}` : `?${paramsH}`  
    // }  
    return buildURL(mergeUrl, params)  
  }  

  // static addQueryString (params) {  
  //   let paramsData = ''  
  //   Object.keys(params).forEach(function (key) {  
  //     paramsData += key + '=' + encodeURIComponent(params[key]) + '&'  
  //   })  
  //   return paramsData.substring(0, paramsData.length - 1)  
  // }

2、buildURL.js

'use strict'  

var utils = require('./utils')  

function encode (val) {  
  return encodeURIComponent(val)  
    .replace(/%40/gi, '@')  
    .replace(/%3A/gi, ':')  
    .replace(/%24/g, '$')  
    .replace(/%2C/gi, ',')  
    .replace(/%20/g, '+')  
    .replace(/%5B/gi, '[')  
    .replace(/%5D/gi, ']')  
}  

/**  
 * Build a URL by appending params to the end  
 *  
 * @param {string} url The base of the url (e.g., http://www.google.com)  
 * @param {object} [params] The params to be appended  
 * @returns {string} The formatted url  
 */  
module.exports = function buildURL (url, params, paramsSerializer) {  
  /* eslint no-param-reassign:0 */  
  if (!params) {  
    return url  
  }  
  var serializedParams  
  if (paramsSerializer) {  
    serializedParams = paramsSerializer(params)  
  } else if (utils.isURLSearchParams(params)) {  
    serializedParams = params.toString()  
  } else {  
    var parts = []  

    utils.forEach(params, function serialize (val, key) {  
      if (val === null || typeof val === 'undefined') {  
        return  
      }  

      if (utils.isArray(val)) {  
        key = key + '[]'  
      } else {  
        val = [val]  
      }  

      utils.forEach(val, function parseValue (v) {  
        if (utils.isDate(v)) {  
          v = v.toISOString()  
        } else if (utils.isObject(v)) {  
          v = JSON.stringify(v)  
        }  
        parts.push(encode(key) + '=' + encode(v))  
      })  
    })  

    serializedParams = parts.join('&')  
  }  

  if (serializedParams) {  
    url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams  
  }  

  return url  
}
  1. utils.js
    
    /**  
    * Determine if a value is an Array  
    *  
    * @param {Object} val The value to test  
    * @returns {boolean} True if value is an Array, otherwise false  
    */  
    function isArray (val) {  
    return toString.call(val) === '[object Array]'  
    }  

/**

  • Determine if a value is an Object
  • @param {Object} val The value to test
  • @returns {boolean} True if value is an Object, otherwise false
    */
    function isObject (val) {
    return val !== null && typeof val === 'object'
    }

/**

  • Determine if a value is a Date
  • @param {Object} val The value to test
  • @returns {boolean} True if value is a Date, otherwise false
    */
    function isDate (val) {
    return toString.call(val) === '[object Date]'
    }

/**

  • Determine if a value is a URLSearchParams object
  • @param {Object} val The value to test
  • @returns {boolean} True if value is a URLSearchParams object, otherwise false
    */
    function isURLSearchParams (val) {
    return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams
    }

/**

  • Iterate over an Array or an Object invoking a function for each item.
  • If obj is an Array callback will be called passing
  • the value, index, and complete array for each item.
  • If 'obj' is an Object callback will be called passing
  • the value, key, and complete object for each property.
  • @param {Object|Array} obj The object to iterate
  • @param {Function} fn The callback to invoke for each item
    */
    function forEach (obj, fn) {
    // Don't bother if no value provided
    if (obj === null || typeof obj === 'undefined') {
    return
    }

    // Force an array if not already something iterable
    if (typeof obj !== 'object') {
    / eslint no-param-reassign:0 /
    obj = [obj]
    }

    if (isArray(obj)) {
    // Iterate over array values
    for (var i = 0, l = obj.length; i < l; i++) {
    fn.call(null, obj[i], i, obj)
    }
    } else {
    // Iterate over object keys
    for (var key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
    fn.call(null, obj[key], key, obj)
    }
    }
    }
    }

module.exports = {
isArray: isArray,
isObject: isObject,
isDate: isDate,
isURLSearchParams: isURLSearchParams,
forEach: forEach
}

  • luch (作者)

    好的,感谢反馈。研究了一下,决定在下个版本加入该功能

    2020-04-16 22:14

  • 今天你很美

    回复 luch: 哈哈,才看见,感谢啊,那我可以直接用npm安装的版本了。还是不习惯这种生态啊,我该直接去你GitHub提pr的。

    2020-05-20 22:18

  • 1***@qq.com

    回复 http.interceptor.request(async (config, cancel) => {

    不能使用 async await函数吗

    2022-12-15 11:31

luch

luch (作者)

作者大大,如果我想要把从后台请求过来的token加到header中怎么做呢??

首先比如说登陆后会返回token;

http.post('login', {userName: '11', password: 'sfsf'}).then(res => {  
    let data = res.data;  
    uni.setStorageSync('token', data.token); // 存入本地储存  
})

要把token 放入header,在全局拦截器修改

http.interceptor.request((config) => { /* 请求之前拦截器 */  
    let token = '';  
    try {  
        let st = uni.getStorageSync('token');  
        if (st) {  
            token = st;  
        }  
    } catch (e) {  
    }  
    config.header = {  
               ...config.header,  
        Token: token // 将token 放入header  

    }  
    return config;  
})
  • 1***@qq.com

    谢谢,作者大大。但是为什么我在http里面加了之后会报错?

    ReferenceError: token is not defined

    at Request.requestBeforeFun (index.js:64)

    at request.js:84

    at new Promise (<anonymous>)

    at Request.request (request.js:62)

    at Request.post (request.js:101)

    at VueComponent.handleLogin (login.vue:64)

    at handleLogin (login.vue?e70c:88)

    at invokeWithErrorHandling (vue.runtime.esm.js:1854)

    at VueComponent.invoker (vue.runtime.esm.js:2179)

    at invokeWithErrorHandling (vue.runtime.esm.js:1854)


    但是用test 没有问题的?现在可以用了,就职这个问题没懂

    2019-07-22 09:39

  • luch (作者)

    回复 1***@qq.com: 是你的代码错误,可以把代码贴上来给你看看

    2019-07-22 10:01

luch

luch (作者)

突然发现这块提问题,没有邮件提示,如果有比较急迫的问题,可以给我发邮件,可以帮你及时处理-邮箱:

webwork.s@qq.com 
1***@qq.com

1***@qq.com - 跨平台开发框架,助我跨平台开发!

import Request from './request'
const test = new Request();
test.setConfig((config) => { / 设置全局配置 /
let token = '';
try{
let st =uni.getStorageSync('token');
if(st){
token = st
}
}catch(e){}
config.baseUrl = 'http://dev.pjy.name:8180/api/bizcust/';
config.header = {
'Content-Type': 'application/json;charset=UTF-8',
"Content-Type": "application/x-www-form-urlencoded",
"Token":token
}
return config
})

test.interceptor.request((config, cancel) => { / 请求之前拦截器 /
config.header = {
...config.header,
'Content-Type': 'application/json;charset=UTF-8',
"Content-Type": "application/x-www-form-urlencoded",

}  
/*  
if (!token) { // 如果token不存在,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行  
    cancel('token 不存在') // 接收一个参数,会传给catch((err) => {}) err.errMsg === 'token 不存在'  
}  
*/  
return config;  

})
test.interceptor.response((response) => { / 请求之后拦截器 /
return response;
})

const http = new Request();
http.setConfig((config) => { / 设置全局配置 /
let token = '';
try{
let st = uni.getStorageSync('token');
if(st){
token = st;
}
}catch(e){
//TODO handle the exception
}
config.baseUrl = 'http://dev.pjy.name:8170/api/bizcust/'; / 根域名不同 /
config.header = {
'Content-Type': 'application/json;charset=UTF-8',
"Content-Type": "application/x-www-form-urlencoded",
...config.header,
Token:token
}
return config
})
http.interceptor.request((config, cancel) => { / 请求之前拦截器 /
config.header = {
...config.header,
b: 1
}

if (!token) { // 如果token不存在,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行  
    cancel('token 不存在') // 接收一个参数,会传给catch((err) => {}) err.errMsg === 'token 不存在'  
}  

return config;  

})
http.interceptor.response((response) => { / 请求之后拦截器 /
console.log(response);
return response;
})
export {
http,
test
};

  • 1***@qq.com

    谢谢作者大大,上面test可以正常使用,但是http的报token的错误

    2019-07-22 16:09

  • luch (作者)

    回复 1***@qq.com: ### 首先大家要注意,静态的设置可以用setConfig 方法,比如说baseUrl、Content-Type、默认请求方式等等,但是动态的,比如说header里面带token,一定要用拦截器,因为确保登录态的存在,使用setConfig 设置,只会设置一次,比如说第一次获取到本地储存后,后面就不会再获取了,而是一直使用之前获取到的。或者还有一种情况,未登录时没获取到本地储存的token,登陆后仍获取不到,以为第一次就没有。所以token设置一定要用拦截器设置(interceptor.request);至于为什么报错,是因为````javascript

    if (!token) { // 如果token不存在,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行

    cancel('token 不存在') // 接收一个参数,会传给catch((err) => {}) err.errMsg === 'token 不存在'

    }


    return config;



    http.interceptor.request 里这段代码你没有注释啊!!!,这段代码只是为了演示cancel()的用法,不过一般不会用的; 还有 几个无用的演示代码,你根据你们的业务逻辑进行删减就可以了

    2019-07-23 09:11

  • luch (作者)


    if (!token) { // 如果token不存在,调用cancel 会取消本次请求,但是该函数的catch() 仍会执行

    cancel('token 不存在') // 接收一个参数,会传给catch((err) => {}) err.errMsg === 'token 不存在'

    }

    2019-07-23 09:13

1***@qq.com

1***@qq.com - 跨平台开发框架,助我跨平台开发!

请问你有遇到过这种情况吗?? 有时候获取不到token的值的情况,我是登录的时候就将token保存进了本地存储!然后再拦截器里面获取本地数据,为什么有时候还会获取不到呢???


就是这样的情况,刷新过后才能获取得到token!!!

*最最最*** 关键的是这个放生的情况是没有规律的,大多数的时候是能获取到token的值的!!
最后是我存入本地的代码


这个写法是有什么问题吗?才会出现这样的问题

  • luch (作者)

    <h2>再次说明:setConfig 方法之后执行一次,就像init 一样。静态的设置可以用setConfig 方法,比如说baseUrl、Content-Type、默认请求方式等等,但是动态的,比如说header里面带token,一定要用拦截器,因为确保登录态的存在,使用setConfig 设置,只会设置一次,比如说第一次获取到本地储存后,后面就不会再获取了,而是一直使用之前获取到的。或者还有一种情况,未登录时没获取到本地储存的token,登陆后仍获取不到,因为第一次就没有。所以token设置一定要用拦截器设置(interceptor.request)</h2>

    2019-07-25 11:22

luch

luch (作者)

再次说明:setConfig 方法之后执行一次,就像init 一样。静态的设置可以用setConfig 方法,比如说baseUrl、Content-Type、默认请求方式等等,但是动态的,比如说header里面带token,一定要用拦截器,因为确保登录态的存在,使用setConfig 设置,只会设置一次,比如说第一次获取到本地储存后,后面就不会再获取了,而是一直使用之前获取到的。或者还有一种情况,未登录时没获取到本地储存的token,登陆后仍获取不到,因为第一次就没有。所以token设置一定要用拦截器设置(interceptor.request

  • 1***@qq.com

    明白了,已经解决了,谢谢!!╰( ̄ω ̄o)

    2019-07-25 12:00

  • 庞123

    回复 1***@qq.com: hi 我这块也遇到在header中设置token不生效的问题了,能告诉一下么

    2022-08-05 12:09

1***@qq.com

1***@qq.com - 热爱生活,热爱编程,热爱学习!

大佬请问请求超时时间如何设置的呀

  • luch (作者)

    回复到下面了

    2019-07-25 17:37

luch

luch (作者)

1***@qq.com

1***@qq.com - 热爱生活,热爱编程,热爱学习!

是不可以自己设置超时时间吗?我看那文档好像没有设置请求超时时间的,比如说我先在这里设置超时时间为2分钟又可以实现的办法吗?


因为我们客户那边的服务器网络有点卡,经常要请求很久才会响应,想哭

  • luch (作者)

    说白了,插件还是对uni.request 的封装,一切都要符合uni-app 规范。不是不能设置,我不是把链接都放在上面了吗?你看那个文档呀!https://uniapp.dcloud.io/collocation/manifest?id=networktimeout 在manifest.json 里设置

    2019-07-26 09:20

  • 1***@qq.com

    回复 luch: 好,谢谢大佬的耐心讲解

    2019-07-26 09:36

1***@qq.com

1***@qq.com - 跨平台开发框架,助我跨平台开发!

作者大大,如果我想在使用了这个插件以后,在某个页面还能继续使用uniapp 的原生请求uni.request吗??? 我该怎么写呢??直接使用可以吗??

1***@qq.com

1***@qq.com - 跨平台开发框架,助我跨平台开发!

作者大大,如果我想在使用了这个插件以后,在某个页面还能继续使用uniapp 的原生请求uni.request吗??? 我该怎么写呢??直接使用可以吗??

  • luch (作者)

    可以直接使用,互不影响的

    2019-07-29 09:37

  • 1***@qq.com

    回复 luch: 好的。明白了

    2019-07-29 09:54

5***@qq.com

5***@qq.com

_request.default is not a constructor; [Component] Event Handler Error @ pages/login/login#handleEvent
TypeError: _request.default is not a constructor
at VueComponent.formSubmit (webpack-internal:///55:55:20)
at eval (webpack-internal:///1:1083:28)
at Array.forEach (<anonymous>)
at eval (webpack-internal:///1:1062:19)
at Array.forEach (<anonymous>)
at z.handleEvent [as __e] (webpack-internal:///1:1052:13)
at Object.r.safeCallback ()
at
at f ()
at

5***@qq.com

5***@qq.com

按照例子用就这样 安卓下

  • luch (作者)

    把引入和使用 代码 发上来看一下

    2019-08-19 10:24

5***@qq.com

5***@qq.com

引入 完全原封不动的。 你能不能起一个APP项目 看看。

  • luch (作者)

    我起了,完全没有问题。

    2019-08-19 11:05

5***@qq.com

5***@qq.com

然后消息头改了下 因为不行 所以我暂时用官方了的 那个请求没问题啊。

5***@qq.com

5***@qq.com

<script>  
        import {    
            mapState,    
            mapMutations    
        } from 'vuex';  
import Request from '../../js_sdk/luch-request/request.js'  
    export default {  
        computed: mapState(['hasLogin','uerInfo']),    
        data() {  
            return {  

            }  
        },  
        onLoad() {  
            uni.setTabBarBadge({  
                index: 2,  
                text: '999'  
            })  
            uni.showTabBarRedDot({  
                index: 3,  
            })  
            //console.log(this.$store.state);  
        },  
        created() {  
        },  
        methods: {  
            tt(){  
                const http = new Request();  
                http.get('/user/me', {  
                    header: {}, /* 会覆盖全局header */  
                    dataType: 'json',  
                    responseType: 'text'  
                }).then(res => {  
                console.log(res);  
                }).catch(err => {  
                console.log(err);  
                })  

            }  
        }  
    }  
</script>

打印出来
15:16:23.149 TypeError: _this2.requestBeforeFun is not a function. (In '_this2.requestBeforeFun(options, cancel)', '_this2.requestBeforeFun' is undefined) at pages/index/index.vue:44

  • luch (作者)

    我千算万算没想到你们会这样用;你可以下载个项目示例看一下;当前版本也可以用,把request.js 里 requestBeforeFun,requestComFun 这两个函数前面的'static' 删除就好了。我会在下个版本更正这个问题;

    2019-08-19 15:37

  • 5***@qq.com

    回复 luch: 因为axios用多了 想跑请求 都直接这样跑。

    2019-08-19 15:49

  • 5***@qq.com

    回复 luch: 现在可以了。 去掉了

    2019-08-19 15:51

9***@qq.com

9***@qq.com - 程序猿

大佬,我加了个delete,然后请求成功返回204;但是成功之后不走then,而是走catch。这个是哪里还需要改吗?

  • luch (作者)

    是因为后台不允许这个请求发放,和代码没关系;让后端在请求方式里把delete 加进去就好了

    2019-08-20 10:15

timcui

timcui

大佬,我想问一下,我怎样加密向后台传递的数据,就是data里边的数据,我用base64加密,传到后台什么都没有了,变成花括号了,这是怎么回事

  • luch (作者)

    是要全部加密还是个别接口解密;全部的话放到拦截器里,个别的话就单独处理;

    <code>回答在下边</code>

    2019-08-27 10:11

  • timcui

    回复 luch: 只是单独加密用户名密码,但是我用了你的办法加密了,但是后台接收到的数据是空的对象

    2019-08-27 16:12

  • timcui

    回复 luch: 谢谢大佬,我知道问题所在了,传递到后台的需要通过对象进行传递.不然后台接收不到数据

    2019-08-27 16:21

luch

luch (作者)

传递加密的数据

/**  
     * @return 加密后的数据  
     * @param {Object} data - 原始参数  
     */  
    let encryptionData = (data) => {  
        let enData = {}  
        for (let key in data) {  
            // encodeURI 替换为你的加密函数  
            enData[key] = encodeURI(data[key])  

        }  
        return enData ;  
    }  
    this.$http.post('login', encryptionData({userName: 'zz', password: '123'}))
张张张啊

张张张啊 - 90后IT男

请求拦截 有cancel 用于 返回 catch 。
但是有需求 响应拦截 也要有 cancel,用于判断返回到 catch 。
statusCode === 200 的情况会有 业务逻辑,需要用到 catch

  • luch (作者)

    会在下个版本加入该需求

    2019-09-10 15:34

luch

luch (作者)

如何解决跨域?
首先要清楚的知道,前端无法从根本上解决跨域(jsonp除外),一般都是后端进行开放端口或者cors,不清楚的可以搜索了解一下。
现在说解决方案:
解决跨域

这个问题都9012年了,还有人问,本来不想回答,问的人太多了。遇到问题要先百度,最后才是问人,不然别人告诉你怎么做,你还是不知道原理。

v***@126.com

v***@126.com - coder

大佬,帮忙看一下baseUrl使用 https:// 的问题啊,卡在这里,明天还得去加班啊

  • v***@126.com

    https好像真的有点问题,使用uni自带的请求是可以的,大佬帮忙看看呢

    2019-09-21 00:04

augustinus

augustinus

你好,我使用uni做了个h5(为后续转化小程序做准备),兼容微信小程序webview,我在请求之后拦截配置如下

http.interceptor.response(  
  response => {  
    /* 请求之后拦截器 */  
    uni.hideNavigationBarLoading()  
    return response  
  },  
  response => {  
    uni.hideNavigationBarLoading()  
    //  校验失败,重新登录  
    console.log(response)  
    if (response.statusCode == 401) {  
      if (window.__wxjs_environment == "miniprogram") {  
        wx.miniProgram.reLaunch({ url: "/pages/welcome/main" })  
      } else {  
        uni.redirectTo({  
          url: "/pages/login/login"  
        })  
      }  
    } else {  
      return response  
    }  
  }  
)

当拦截器进入error时,本地打印如下截图

打包后放在服务器打印如下

augustinus

augustinus

刚刚截图搞混了 ,
在微信open-data里打开h5 ,在微信开发者工具里截图如下

本地未打包前


打包后在服务器

在Chrome浏览器里直接访问截图如下:
本地未打包前


打包后在服务器

所有截图的触发同一个api(之前截图有get请求,是另外一个api)
可以发现打包后errMsg由‘request:ok’ 变成 “request:fail”
直接导致没有statusCode 和 data 值

  • luch (作者)

    加我qq

    370306150,request fail 这个是uni.request 返回的错误,表示请求没有发出,这种情况一般是哪里配置错了,比如没有安全域名等等

    2019-10-10 09:13

  • augustinus

    回复 luch: 嗯,多谢,已经解决了

    2019-10-12 15:09

luch

luch (作者)

土豪赞赏!
<br>

sun_wenming

sun_wenming

您好,请问一下请求支持同步么?如何支持如何实现呢?

  • luch (作者)

    uni-app 没有提供同步的api。你可以根据自己的业务场景去处理。Generator、async await 。

    2019-10-24 17:38

  • sun_wenming

    回复 luch: 好的,谢谢。

    2020-02-11 12:13

NikoRanger

NikoRanger

大佬,我这边使用的是Session 登陆,由于Cookie没有传到后台导致每次请求的sessionId都不一样,导致我获取不到登陆状态,我查到axios 有一个配置:axios.defaults.withCredentials=true;

这个插件有这样的配置吗

  • luch (作者)

    uni-app 如果你只考虑h5端的话可以用,cookie存在,请求时会自动携带。如果有其他端的话,就要和后端商量其他方式了。

    <br>------------------------<br>

    建议<br>

    一. 建议换成token 验证

    二.


    https://ask.dcloud.net.cn/question/59558

    2019-10-30 08:58

1***@qq.com

1***@qq.com - 跨平台开发框架,助我跨平台开发!

作者大大,又遇到了一个问题,之前后台只传了一个token过来,现在改成两个,我怎么去自动刷新token,(用户调用一个接口。但是token已经过期了,现在用第二个token去获取第一个接口需要的token,这个过程是自动的,用户感知不到的)这个需要怎么做呢?
《token过期时web前端如何自动刷新token,以token处理登录的web系统,一般会有两个token:access-token和refresh-token。》

8***@qq.com

8***@qq.com

支持微信小程序吗?

  • luch (作者)

    通用的,理论上是全端支持。个人目前已在微信小程序,app,h5 上过项目了。其他端小程序本人没有做过对应开发。目前没有任何人反馈在小程序端不支持。插件开发完全遵循uni规范,所以支持

    2020-02-11 15:19

1***@qq.com

1***@qq.com - 跨平台开发框架,助我跨平台开发!

请问,在拦截里面可以跳转页面吗?现在有个需求就是如果后台返回-10000就是用户登录过期了,需要直接跳转到登录页。请问可以使用this.$router.push吗??

  • luch (作者)

    可以,加个防抖,不然多个接口响应会调用多遍

    2020-03-07 13:35

  • 1***@qq.com

    回复 luch: 怎么将this指向vue?具体怎么做能告知下吗?我试来好多办法都行不通!!!防抖又是什么意思。我现在 做的就是判断返回结果是否是token过期(-10000)只有结果在过期的情况才会跳到登录页! 谢谢了

    2020-03-07 15:27

  • luch (作者)

    回复 1***@qq.com: 你这个$router 应该是在main.js挂载的。 Vue.prototype.$router = c; 你把这个c 在request这个拦截器的js 文件引入。 c.push() 。js 防抖 可以在网上了解一下,有问题可以加我q

    2020-03-07 18:22

  • 1***@qq.com

    我加了你的qq,我在使用你告诉我的方法的时候还是有点问题。您说的那个c是的什么属性。赋值后不需要暴露出去吗?在拦截器index. js里面是通过import引入吗?

    2020-03-07 21:37

8***@qq.com

8***@qq.com

作者你好,插件非常好用,本人前端小白在nvue页面调用插件请求时出现了错误


这是插件在全局的引用

在nvue界面调用时出现了这样的错误,在其他vue页面都可以使用,因为对nvue了解较少也参考了官方文档没有看到不支持的api,所以很困扰,请问这是什么问题?

  • luch (作者)

    nvue 不支持全局挂载 。 局部引入试试! 把import {http } from '' 放在nvue 页面。

    2020-03-07 19:50

  • 8***@qq.com

    回复 luch: 可以了,还是对前端这些知识不太了解,谢谢你

    2020-03-07 20:03

社交软件联盟

社交软件联盟 - 免费的社交软件开发框架和运营支持合作联盟

header: {  
      'Content-Type': 'application/json;charset=UTF-8'  
    },

百度小程序真机调试不兼容,但是开发者工具可以用,很奇怪。发布后也不能用,所以必须改为以下方式

只能使用

header: {  
      'Content-Type': 'application/json'  
    },
无忧模板

无忧模板 - 无忧模板,基于uniapp做全行业的项目模板整合,做标准化的模板开创者

问题:
token 过期后 返回401,在 response 拦截器中, 我拿着 refreshToken去换取新token 这是没问题的。但是如何再次调取原接口返回?

我可以拿到 response 的参数 继而拿到上次请求的链接 方法 参数。

如果用response 的参数来判断,根据不同的请求类型 再次发起请求。过于繁琐。请问有什么好办法解决吗?

  • luch (作者)

    1.在请求拦截器判断token 的过期时间小于一分钟,通过refreshToken 请求新的token, 更新token, token 过期时间。整个过程是无感知的,实现起来也简单

    <br>



    1. 像你这样在响应拦截器修改,其实是需要一个sleep 的。await async,这个我在示例项目里有提供思路。主要还是解决sleep 问题。

    2020-03-23 15:20

无忧模板

无忧模板 - 无忧模板,基于uniapp做全行业的项目模板整合,做标准化的模板开创者

3Q。

日月月

日月月

大佬支持多文件上传吗?

1***@qq.com

1***@qq.com - 我是小提莫

项目写的太复杂了,不会用!全局引入之后,页面一调用就报错!```javascript
thirdScriptError
15:08:27.471 undefined is not an object (evaluating 'this.$http.post'); [Component] Event Handler Error @ pages/user/login/login#handleEvent

我页面中的代码:

const datas = {
phone: this.tel,
password: this.pwd,
systemCode: 'S1003'
};
this.$http.post('/sso/ssoUser/login/phone', {}, {
params: datas
}).then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})

  • luch (作者)

    挂载了吗? 打印 this.$http 看有东西吗? 把引入、挂载代码发出来

    2020-03-31 15:20

  • 1***@qq.com

    回复 luch: 挂载了,main.js: // 引入request库(加拦截器最终版本)

    import $http from '@/common/http/index.js';

    Vue.prototype.$http = $http

    2020-03-31 15:25

  • luch (作者)

    回复 1***@qq.com:

    你这问题太基础了。自己学一下export default 和export 的区别

    <br>


    `

    // http/index.js

    export {

    http

    }


    // main.js

    import {

    http

    } from '@/utils/luch-request/index.js'

    Vue.prototype.$http = http

    `

    2020-03-31 15:36

  • 1***@qq.com

    回复 luch: 好吧,没主意

    2020-03-31 15:46

1***@qq.com

1***@qq.com - 我是小提莫

还有个问题,我想每个请求都走那个防抖闭包应该怎么操作呢?想禁止用户按钮连点

3***@qq.com

3***@qq.com - 企点邦

请教一下 一直提示错误错误:ReferenceError: token is not defined

  • luch (作者)

    'token' 这个变量使用了,但是没有定义

    2020-04-07 11:22

l***@163.com

l***@163.com

你好,我用的get方法,使用下列api url: http://xxx/xxxx/roles/?page=1&perPage=20 能返回正确的数据,但是使用api url: http://xxx/xxxx/roles/ 就会返回错误(errMsg: "The browser (or proxy) sent a request that this server could not understand." )。为什么?

xiaoyuZ

xiaoyuZ

求解;可以结合环境变量使用吗? 还有如果结合了环境变量 可以兼容APP吗

h***@outlook.com

h***@outlook.com - 前端开发

使用npm安装插件。在main.js使用 import Request from 'luch-request' 方式引用。在H5运行时一切正常。
在将uniapp运行到app-plus时(Android真机),报错:

16:49:23.202 reportJSException >>>> exception function:createInstanceContext, exception:white screen cause create instanceContext failed,check js stack ->Exception: SyntaxError: Unexpected token '...'. Expected a property name.  
16:49:23.225 at weex createInstanceContext:2689  
16:49:23.269 getTemplateInfo== template md5 ca4105dabcc32b1901ed8472f6bfd6a4 length 587765 base64 md5 ykEF2rzDKxkB7YRy9r/WpA== response header {"templateSourceBase64MD5":["ykEF2rzDKxkB7YRy9r/WpA=="],"templateSourceMD5":["ca4105dabcc32b1901ed8472f6bfd6a4"]}

经过控制变量测试,确认此报错信息由此插件引用导致。请问有什么解决方案吗?

  • h***@outlook.com

    经过多次实验,发现使用HBuilder安装的版本,然后通过相对路径import的可以正确编译。而通过npm安装,然后直接引入包的,编译时报错。目前不能确认错误来源是插件本身的npm版本有误,或者是由于通过vue create -p dcloudio/uni-preset-vue my-project创建的uniapp项目,其webpack配置有问题

    2020-06-09 17:21

  • luch (作者)

    好的,收到

    2020-06-09 18:03

  • luch (作者)

    回复 h***@outlook.com: 可以加一下qq 370306150看一下。我当前用hbuilderx 创建一个uni-app 项目,npm 安装,手机连线运行在安卓。没有遇到报错。正在安装cli 项目进行测试

    2020-06-09 21:16

  • luch (作者)

    回复 h***@outlook.com: cli 项目确实复现了。增加这个配置quanzhan.co。我增加这个配置后就可以了

    2020-06-09 22:31

  • h***@outlook.com

    回复 luch: 谢谢,采用此方案能解决。

    2020-06-10 16:17

3***@qq.com

3***@qq.com - 企点邦

报错:errMsg": "request:fail abort statusCode:-1”

  • luch (作者)

    请提供更加详细的信息

    2020-06-16 23:27

旺仔牛奶

旺仔牛奶 - 一定要开心呀~

请问 upload 可以上传除了图片视频 可以上传其他如 word excel text 等 其他格式的文件吗?

下一页丶翻

下一页丶翻

问下为啥的http的请求,自动给我补了给s变成https的请求,这样会出现发送的请求方式只能说get请求,能设置不让它补成https么

  • luch (作者)

    插件没有自动补https此项功能。检查其他原因

    2020-09-15 16:14

下一页丶翻

下一页丶翻

请教下,请求后拦截为啥我不return返回结果,还是给我返回到then里面去了!如果想阻止返回怎么办!比如:我401的时候我重新刷新了token,再次请求了数据接口,但是401的时候就给我返回到then里面去了(但是我请求后,拦截器是没return回去的)

;这样我后面刷新后的数据 就没法到then里面了

十八岁想唱Rap

十八岁想唱Rap - rap

你好!全局引用,请求之后拦截写在哪里呢?

飞哥正传

飞哥正传

问一下,可以设置请求Cookie的Secure属性吗,之前那个session丢失可能是这个问题。

大帅哥2

大帅哥2

BUG
post 访问 拦截返回信息 header里面内容获取不到

  • luch (作者)

    这个header 是uni 返回的,说明确实获取不到,并非插件bug。你可以用uni.request 试一下。

    2020-11-17 09:45

3***@qq.com

3***@qq.com - wangdefa

http.middleware({
method: 'POST', // 请求方法必须大写 [GET|POST|PUT|DELETE|CONNECT|HEAD|OPTIONS|TRACE|UPLOAD|DOWNLOAD]】
请求不支持PATCH,希望能加进去。

  • luch (作者)

    回复见楼下

    2020-12-04 15:35

luch

luch (作者)

uni request 只支持这些方法。不支持PATCH,我爱莫能助。

smallsuper

smallsuper

upload上传失败
前端代码
上传图片.vue
evaluateUploadPhoto({
filePath: this.imagesData[i],
name: 'photo',
header: {
'token': uni.getStorageSync('token')
}
})

index.js
/**

  • 上传图片
    */
    export const evaluateUploadPhoto = params => (
    http.upload('/evaluate/upload-photo', params)
    )

mergeConfig.js
// eslint-disable-next-line no-empty
if (method === 'DOWNLOAD') {

} else if (method === 'UPLOAD') {
config.method = 'POST'
delete config.header['content-type']
delete config.header['Content-Type']
const uploadKeys = [
// #ifdef APP-PLUS || H5
'files',
// #endif
// #ifdef MP-ALIPAY
'fileType',
// #endif
// #ifdef H5
'file',
// #endif
'filePath',
'name',
'formData',
]
uploadKeys.forEach(prop => {
if (typeof config2[prop] !== 'undefined') {
config[prop] = config2[prop]
}
})
}

请求记录

后台报错
/evaluate/upload-photo错误:系统错误Current request is not a multipart request

  • luch (作者)

    不要改插件源码啊

    2020-12-16 18:21

  • smallsuper

    回复 luch: 去掉修改的部分就正常了,不好意思

    2020-12-17 10:33

十八岁想唱Rap

十八岁想唱Rap - rap

originalData: true, // 是否在拦截器中返回服务端的原始数据
这个有点问题,按文档应该是true 返回的 res.data值 不是 res值,为了失败的时候弹出错误提示,尝试了几次 开关现在 设置为 true返回的是res,感觉不是很稳定

  • luch (作者)

    你看的哪里的文档???这个也不是我插件的功能啊

    2020-12-30 09:28

wejarchan

wejarchan

你好,我想上传文件使用PUT请求,这个能做到吗?
我需求是想传图片上 云服务器 对象存储 上边。调用 putObject接口的,要PUT 请求和传输文件的

  • luch (作者)

    你的思路不对。用微信小程序的sdk。 cos-wx-sdk-v5.js。实例化后用的都是cos的方法。如果还是不清楚。重新开贴,详细描述问题,我给你看一下

    2021-01-13 17:24

HZH8997

HZH8997

大佬好,想请问一下,设置baseURL,在本地运行的时候,请求的接口会加上 http://localhost:8080/#

最终请求接口 http://localhost:8080/www.zv123.com/api/config/get

404....

  • HZH8997

    不好意思,怪我,【https://】忘了加;叨扰了~(插件很OK,双手奉上5星)

    2021-04-24 15:07

  • luch (作者)

    回复 HZH8997: 修改全局配置不要直接改源码。全局配置修改方法

    2021-04-27 11:43

5***@qq.com

5***@qq.com

返回的数据会从新排序问题,

  • luch (作者)

    插件 没有对response 做任何操作,可以用 postMan 看一下结果集。再用uni.request 试一下

    2021-06-15 10:53

1***@qq.com

1***@qq.com

大佬你的插件我踩了一个坑了,或者说是跨域的坑吧,有需要跨域的请看https://ask.dcloud.net.cn/article/39309

1***@qq.com

1***@qq.com

作者你好,请教个问题,我以h5方式在浏览器访问项目,已设置withCredentials: false,但发布项目后请求headers中还是携带了cookie,请问是什么原因?

  • luch (作者)

    XMLHttpRequest.withCredentials


    <br>


    先看一下定义。


    <br>


    它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。在同一个站点下使用withCredentials属性是无效的。


    <br>


    在同域下,不论你是否设置,都会携带。


    <br>

    同域请求时会带上cookie, 跨域请求不会, 跨域请求需要设置 withCredentials 和服务端响应头

    2022-05-16 10:29

5***@qq.com

5***@qq.com

const options = {  
    // 显示操作成功消息 默认不显示  
    showSuccess: false,  
    // 成功提醒 默认使用后端返回值  
    successMsg: '',  
    // 显示失败消息 默认显示  
    showError: true,  
    // 失败提醒 默认使用后端返回信息  
    errorMsg: '',  
    // 显示请求时loading模态框 默认显示  
    showLoading: true,  
    // loading提醒文字  
    loadingMsg: '加载中',  
    // 需要授权才能请求 默认放开  
    auth: false,  
    // ...  
};  

// Loading全局实例  
let LoadingInstance = {  
    target: null,  
    count: 0,  
};  

/**  
 * 关闭loading  
 */  
function closeLoading() {  
    if (LoadingInstance.count > 0) LoadingInstance.count--;  
    if (LoadingInstance.count === 0) uni.hideLoading();  
}  

const header = {  
    // Accept: 'text/json',  
    'Content-Type': 'application/json;charset=UTF-8',  
    platform: $platform.name,  
    'x-ma-version': 100,  
    'x-mt-date': new Date().toUTCString(),  
}  

/**  
 * @description 请求基础配置 可直接使用访问自定义请求  
 */  
const http = new Request({  
    baseURL: baseUrl,  
    timeout: 8000,  
    method: 'GET',  
    header,  
    // #ifdef APP-PLUS  
    sslVerify: false,  
    // #endif  
    // #ifdef H5  
    // 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+)  
    withCredentials: false,  
    // #endif  
    custom: options,  
});  

/**  
 * @description 请求拦截器  
 */  
http.interceptors.request.use(  
    (config) => {  
        if (config.custom.auth && !$store('user').isLogin) {  
            showAuthModal();  
            return Promise.reject();  
        }  
        if (config.custom.showLoading) {  
            LoadingInstance.count++;  
            LoadingInstance.count === 1 &&  
                uni.showLoading({  
                    title: config.custom.loadingMsg,  
                    mask: true,  
                    fail: () => {  
                        uni.hideLoading();  
                    },  
                });  
        }  
        return config;  
    },  
    (error) => {  
        return Promise.reject(error);  
    },  
);  

const request = (config) => {  
    let token = $store('user').userInfo.token?? '';  
    http.config.header['x-app-id'] = 'hideMyAppid';  
    http.config.header['x-app-version'] = $store('app').info.version;  
    if (!!token) {  
        http.config.header['x-open-id'] = token  
    }  
    if (config.url[0] !== '/') {  
        config.url = apiPath + config.url;  
    }  
    // 测试环境及前端本地开发时在httpHeader带个参数 x-gray-version:test   
    if (baseUrl.includes('api-test')) {  
        http.config.header['x-gray-version'] = 'test'  
    } else if (baseUrl.includes('api-dev')) {  
        http.config.header['x-gray-version'] = 'develop'  
    }  
    return http.middleware(config);  
};  

export default request;

作者你好,请问为什么3.X版本请求返回的数据,如果出现数据报错异常会先在Promise.then()中返回false,然后再走catch?

  • luch (作者)

    数据异常是什么情况,每个人理解的数据异常都不一样,最好是能举个例子。你的调用,你异常时的返回。又走then 又走catch,有可能是 then 里 return Error 或者 会变成reject状态的 Promise 。目前看你上面的代码没有问题。最好能附上可复现的demo,或者联系qq 发送demo

    2023-11-29 09:22

  • 5***@qq.com

    回复 luch: 所有接口的报错都是先走then返回一个false,然后再走catch。但是换回uni.request的简单封装又只走catch了,很奇怪。我用的是上面配置发送的数据,目前还是没发现是什么原因导致的。

    2023-12-17 03:21

foxGhost

foxGhost

使用中遇到一个问题, 无法获取完整的response header. 只能拿到
cache-control 和 content-type
我想拿到其他 response header的值应该如何设置

要回复问题请先登录注册