弈凌
弈凌
  • 发布:2023-03-19 19:23
  • 更新:2023-03-21 11:10
  • 阅读:695

uni.addInterceptor('request' 中,如何阻止错误请求继续执行

分类:uni-app
uni.addInterceptor('request', {  
    success(resp) {  
        // http状态码响应的是400-500等,也会进入成功拦截  
        // 如何在这里判断服务端响应异常后,阻止前端逻辑继续执行  
        // Promise是可以阻止的,但uni.request阻止不了  
    },  
    fail(err) {  
    }  
})

问题已解决,拦截器中return false即可

2023-03-19 19:23 负责人:无 分享
已邀请:
zZZ1Ma

zZZ1Ma

提供一下我的拦截器核心代码,希望对你有用

uni.addInterceptor('request', {  
  invoke: args => {  
    // 不在免校验(token)白名单且未登录则取消此次request  
    if (!whiteList.includes(args.url) && !token) {  
      return false // 返回false则会取消本次request  
    }  
    // 预设并补全参数  
    Object.assign(args, {  
      enableHttp2: true,  
      enableCache: true,  
      url: `https://xxxx.cn/${args.url}`,  
      header: { 'token': token },  
    })  
  },  
  returnValue: p => new Promise((resolve, reject) => p.then(({  
    statusCode,  
    data: { data, msg, status, ...args }  
  }) => {  
    // 我这里只有200是成功,其余状态(例如你说的400、500等)则使其进入fail()或catch()  
    if (statusCode !== 200) reject({ status: statusCode })  
    // 此处正常返回解构后的参数,在success()或then()可获取返回值  
    resolve(Object.assign({ status, ...data, ...args }, msg && { title: msg }))  
  }))  
})
  • 弈凌 (作者)

    你好,returnValue这段代码会抛出异常:Uncaught (in promise) TypeError: p.then is not a function


    我尝试这样(如下),实现了终止错误请求继续执行逻辑的需求,但不确定是否有问题。


    returnValue(args) {  
    args._xhr.onprogress = function(event) {
    if (args._xhr.status != 200) {
    args.abort();
    }
    }
    }

    2023-03-21 11:29

  • 弈凌 (作者)

    同时还有一个需求,发现实现不了,就是在拦截器中修改响应值,比如:每个响应体中都有一个字段id,统一修改为_id,类似此需求,就是修改响应体,解决这个问题:https://ask.dcloud.net.cn/question/163714

    2023-03-21 11:32

  • zZZ1Ma

    回复 弈凌: vue2项目参考这里转换https://uniapp.dcloud.net.cn/api/

    2023-03-21 11:32

  • zZZ1Ma

    回复 弈凌: returnValue(args)这里的args是Promise{<pending>}吗,不是当然无法使用then()

    2023-03-21 11:34

  • zZZ1Ma

    回复 弈凌: 这里逻辑有问题,因为request调用了,你在request返回结果里再去abort()终止已经发出的请求?

    2023-03-21 11:36

  • 弈凌 (作者)

    回复 2***@qq.com: 多谢解惑,这个问题已经解决了,只需要在success拦截中,return false即可阻止后续成功逻辑执行(uni.request中也不会再执行success方法)


    我是vue3项目,上面的方法确实会抛出异常:Uncaught (in promise) TypeError: p.then is not a function


    我梳理下,我确实有两个需求:1. 在拦截器中阻止错误响应执行 2. 在拦截器中修改响应内容

    2023-03-21 11:42

  • zZZ1Ma

    回复 弈凌: returnValue(args)=> args.then();

    1:在addInterceptor外申明一个变量,记录此次请求的状态(错误or正确),returnValue内实时更改此次请求状态并赋值到该变量;然后在invoke内判断,错误则返回false取消本次请求

    2:更改响应内容,我在上面的代码不是把返回的msg更改成title了?

    2023-03-21 11:49

  • 弈凌 (作者)

    回复 2***@qq.com: 现在还剩下一个问题,如何在request拦截器中修改响应体,args._xhr是一个RequestTask对象

    2023-03-21 11:52

  • zZZ1Ma

    回复 弈凌: 解构对像啊

    2023-03-21 11:53

  • 弈凌 (作者)

    回复 2***@qq.com: 你好,上述代码,我这边执行失败了,如果可以的话,我想提供一份示例,你帮我看下哪里有错误(有偿的)

    2023-03-21 11:54

  • zZZ1Ma

    回复 弈凌: 你加我QQ 227936048,提供一份最简单demo,一两个页面那种哦

    2023-03-21 11:56

  • 弈凌 (作者)

    回复 2***@qq.com: 这个RequestTask对象中的值,需要在延迟任务setTimeout或_xhr.onprogress中才能获取到,并且不能修改,提示是只读属性。

    2023-03-21 11:57

  • zZZ1Ma

    回复 弈凌: 那就没办法,已经尽力帮助你了。你这个代码比较复杂,可否在onprogress()内解构呢?


    onprogress:event=>{  
    const { } = event // 这样解构
    let _id = event.xx.id // 或是这样赋值
    }

    2023-03-21 12:03

  • zZZ1Ma

    回复 弈凌: uni.request()内不要传入callback(success / fail / complete任一个),否则returnValue内返回的是RequestTask对象


    uni.request({ url: '', data: {} })  
    .then(result => console.log(result)) // 状态码为200的结果
    .catch(error => console.log(error)) // 状态码不为200的结果,可故意将url少写一个字母复现

    2023-03-21 12:13

  • 弈凌 (作者)

    回复 2***@qq.com: 牛批,确实是这样,问题已解决,多谢!

    2023-03-21 13:13

DCloud_UNI_WZF

DCloud_UNI_WZF

uni.request 类似 fetch 只有请求失败(比如跨域)才会进入 fail 回调,而业务层的失败(返回 400 ,500)并不会进 fail 回调,针对这种情况,建议基于业务需求对 uni.request 进行封装,以区分业务的成功,失败

  • 弈凌 (作者)

    明白,感谢回复。就不再包一层了,我还是在每个request中加个判断吧,如果官方能支持拦截器中返回一个Boolean值来阻断业务中的执行,就完美了。


    大佬,还有一个问题,请问能一起解决了么。https://ask.dcloud.net.cn/question/164068

    拦截器中处理返回值,其实是这个问题的延展:https://ask.dcloud.net.cn/question/163714


    目前还是在每个request中,单独处理。我想在拦截器中统一处理下,不论是这个阻止业务执行(支持返回boolean值阻止),还是响应值的修改,都是希望技术与业务分离,该在拦截器中统一处理的就统一处理,而非每个方法都搞一遍。

    2023-03-20 17:07

  • DCloud_UNI_WZF

    回复 弈凌: https://ask.dcloud.net.cn/question/164068 已回复过提供可复现的demo

    https://ask.dcloud.net.cn/question/163714 该问题也已在帖子中讨论过 uni.request 的定位类似 fetch 而不是 axios

    2023-03-20 17:15

  • 弈凌 (作者)

    回复 DCloud_UNI_WZF: 你好,示例demo已提供,请问这个在拦截器中阻断在页面中的request.success执行的能力,后续会考虑提供么

    2023-03-20 18:28

  • DCloud_UNI_WZF

    回复 弈凌: 不会

    2023-03-20 18:35

  • 弈凌 (作者)

    回复 DCloud_UNI_WZF: 如何可以的话,还是考虑下吧,谢谢。

    原因如下:



    1. 期望在拦截器中统一处理错误,比如提示用户

    2. 已经出现了错误的请求,再去执行正确的业务逻辑已经没有任何意义了,反倒会引发其他错误

    2023-03-20 18:41

  • zZZ1Ma

    回复 弈凌: 看一下我贴在二楼的代码,仅适用于Vue3(vue2须自行转换),可满足你的需求

    2023-03-21 11:15

  • 弈凌 (作者)

    回复 DCloud_UNI_WZF: 你好,获得后端错误响应后,拦截器中阻止success执行,只需要retruen false就可以了,可以的话,建议在文档中补充下说明

    2023-03-21 12:10

要回复问题请先登录注册