uni-app中uni.addInterceptor('request')拦截器在只调用一次api接口时,发现拦截器会被触发很多次

uni-app中uni.addInterceptor(‘request’)拦截器在只调用一次api接口时,发现拦截器会被触发很多次

示例代码:

uni.request({  
    url: 'request/login', //仅为示例,并非真实接口地址。  
    success: (res) => {  
        console.log(res.data);  
        // 打印: {code:1,...}  
    }  
});  

uni.addInterceptor('request', {  
  invoke(args) {  
    // request 触发前拼接 url   
    args.url = 'https://www.example.com/'+args.url  
    console.log(args.url)  
  },  
  success(args) {  
    // 请求成功后,修改code值为1  
    args.data.code = 1  
  },   
  fail(err) {  
    console.log('interceptor-fail',err)  
  },   
  complete(res) {  
    console.log('interceptor-complete',res)  
  }  
})

操作步骤:

只调用一个api接口一次,然后在invoke函数里打印args.url会发现被触发了很多次,打印多次重复结果

预期结果:

只打印一次结果console.log(args.url)

实际结果:

打印了很多次重复结果console.log(args.url)

bug描述:

uni-app uni.addInterceptor(‘request’)拦截器,当前页面只调用了一个api接口发现拦截器被触发很多次


| 信息类别         | 信息内容                     |
|------------------|------------------------------|
| 产品分类         | uniapp/小程序/微信           |
| PC开发环境       | Mac                          |
| PC开发环境版本   | Mac big sur 11.6.1           |
| HBuilderX类型    | Alpha                        |
| HBuilderX版本    | 3.2.15                       |
| 第三方工具版本   | 1.05.2110290                 |
| 基础库版本       | 2.21.0                       |
| 项目创建方式     | HBuilderX                    |

更多关于uni-app中uni.addInterceptor('request')拦截器在只调用一次api接口时,发现拦截器会被触发很多次的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

请问这个拦截器配置在什么地方能使全局的请求都被拦截到呢?

更多关于uni-app中uni.addInterceptor('request')拦截器在只调用一次api接口时,发现拦截器会被触发很多次的实战教程也可以访问 https://www.itying.com/category-93-b0.html


没人给解释下原因吗? 每次请求都会比上一次多打印一次

得弄成全局拦截,每次调用都拦截了会重复打印

这是一个已知的拦截器重复触发问题,通常由以下原因导致:

主要原因:

  1. 拦截器注册时机问题:如果拦截器注册在页面生命周期中(如onLoad),每次页面刷新或重新进入时都会重复注册
  2. HBuilderX热重载:开发环境下,代码保存后热重载可能导致拦截器重复绑定
  3. 拦截器全局性uni.addInterceptor添加的是全局拦截器,多次调用会叠加而非替换

解决方案:

方案一:确保拦截器只注册一次

// 在App.vue的onLaunch中注册,确保全局只注册一次
export default {
  onLaunch() {
    // 添加判断避免重复注册
    if (!this._requestInterceptorAdded) {
      uni.addInterceptor('request', {
        invoke(args) {
          args.url = 'https://www.example.com/' + args.url
          console.log('请求URL:', args.url)
        },
        success(args) {
          if (args.data) {
            args.data.code = 1
          }
        }
      })
      this._requestInterceptorAdded = true
    }
  }
}

方案二:使用单例模式

// 创建拦截器管理模块
let requestInterceptorAdded = false

export const setupRequestInterceptor = () => {
  if (requestInterceptorAdded) return
  
  uni.addInterceptor('request', {
    invoke(args) {
      args.url = 'https://www.example.com/' + args.url
    },
    success(args) {
      if (args.data) {
        args.data.code = 1
      }
    }
  })
  
  requestInterceptorAdded = true
}

// 在App.vue中调用
import { setupRequestInterceptor } from '@/utils/interceptor'
setupRequestInterceptor()

方案三:检查并移除已存在的拦截器(HBuilderX 3.3.0+)

// 先移除可能存在的拦截器
try {
  uni.removeInterceptor('request')
} catch(e) {
  // 忽略不存在的错误
}

// 再添加新的拦截器
uni.addInterceptor('request', {
  invoke(args) {
    args.url = 'https://www.example.com/' + args.url
  }
})

注意事项:

  1. 避免在页面生命周期中注册全局拦截器
  2. 生产环境打包后此问题通常不会出现
  3. 检查是否有多个地方调用了uni.addInterceptor('request')
  4. 确保没有在组件或页面的多次渲染中重复注册

临时验证:

在开发阶段,可以在拦截器invoke方法中添加唯一标识验证:

let count = 0
uni.addInterceptor('request', {
  invoke(args) {
    count++
    console.log(`第${count}次调用拦截器`)
    args.url = 'https://www.example.com/' + args.url
  }
})
回到顶部