uni-app 整个应用接口请求阻塞

发布于 1周前 作者 vueper 来自 Uni-App

uni-app 整个应用接口请求阻塞

操作步骤:

  • 在一个页面请求接口,这个接口响应时间设置很久。然后退出当前页面。进去其他页面。其他页面的接口请求没有发出

预期结果:

  • 每个页面是每个页面的请求。互不影响

实际结果:

  • 其中一个页面接口请求较慢会影响其他页面的接口请求无法发出

bug描述:

  • 整个应用接口请求阻塞
  • 在安卓端,场景:当我进入某个页面,这个页面的接口请求要很久。然后我退出了这个页面,我再进入其他页面,发现其他页面的接口请求都没有执行。只有当之前那个页面的接口请求完成或者进入了请求超时fail了之后,其他页面的接口请求才会发出,这个是为什么呢?
  • H5端不会出现这个情况

附件

信息类别 详细信息
产品分类 uniapp/App
PC开发环境操作系统 Windows
PC开发环境操作系统版本号 windows 10
HBuilderX类型 正式
HBuilderX版本号 4.28
手机系统 Android
手机系统版本号 Android 14
手机厂商 vivo
手机机型 iQOO Neo9S Pro
页面类型 vue
vue版本 vue3
打包方式 云端
项目创建方式 HBuilderX
App下载地址或H5网址 https://app.liuyingyong.cn/build/download/dd168b70-8c2e-11ef-b172-bd30c1125d82

21 回复

有官网的人能验证一下吗?还是说我的代码有问题呢?


来个h5网址看看

H5测试是正常的,切换页面后的接口请求正常,安卓app不行

回复 p***@163.com: 抓包看了吗?是一直在请求?是不是有条件编译语句区分的逻辑

你好,根据你的描述模拟了一个场景:在 A 页面点击请求后跳转到 B 页面,A 页面的请求会有延迟 3s 后返回,并且通过拦截器进行一个请求前的提醒,执行结果如下:

点击发起请求后,立刻跳转到 B 页面,B 页面请求正常发出
另外我注意到,你的项目看起来都已经开发很久了,为啥做了这么多之后才发现这个问题?是更新 Hx 版本导致这个问题吗?如果您有疑问,可以提供一个类似的可复现工程。
附带测试项目

这个是在做优化的时候发现的。会不会是因为http1.1的问题呢?我后续新建一个项目测试一下

我看了你这个测试项目,其实也是等index中的请求完成了之后,home页面中的请求才会完成。

你将index中请求时长设置久一点。那home的请求是不是就要一直等待index页面中的请求完成了之后才会成功呢,这种情况是不对的吧

@DCloud_UNI_yuhe 你看下这个复现工程

你好,我这里测试过,安卓模拟器和安卓真机,ios 模拟器和 ios 真机,和 web 平台,在经过这些平台的测试中,只发现了 Android 模拟器有这个问题,这个问题可能是模拟器问题,你尝试使用真机测试一下是否存在这个问题,我这里测试真机是正常的。

我们测试IOS也是一样的,我们的接口请求超时时间设置的是1分钟,其中A页面的接口会一直在请求。然后退出A页面,进入其他任何页面的接口请求都会阻塞,就好像还在队列中一样。只有等A页面的那个接口完成或者终止了,其他页面的接口请求才会成功,我们想要的是A页面的接口请求,不会影响到其他页面的接口,是否有办法能处理?

web平台不会出现这种情况是因为web是http2.0的。而APP端还是http1.x

@DCloud_UNI_yuhe 请问一下,这个是不是因为APP用的是http1.1的,所有接口请求都是复用一个通道,然后第一个接口的请求未完成,导致后面的接口请求还在队列,我们想避免这种情况有什么办法能处理吗?

你是测试 ios 真机还是模拟器有这个问题?安卓真机呢?

回复 DCloud_UNI_yuhe: 都是这个问题。安卓模拟器,安卓真机,IOS真机

回复 p***@163.com: 你服务器没有改什么东西吗?我今天测试的时候安卓模拟器也正常了,真奇怪了

回复 DCloud_UNI_yuhe: 没改啥东西。我刚刚重新用我发的那个http-test测试项目看还是一样的,我重新录一个完整的演示给你看下

回复 p***@163.com: 好的,不用,我这里也能复现这个问题,但就是平台有差异,我问一下

回复 DCloud_UNI_yuhe: 好的

回复 p***@163.com: 你好,看一下私信。

在uni-app中,如果整个应用的接口请求出现阻塞问题,通常是因为多个请求并发执行导致服务器压力过大,或者前端没有合理处理请求队列。以下是一些代码案例,展示如何在uni-app中处理这种情况,以避免接口请求阻塞。

1. 使用请求队列管理

可以使用一个简单的队列来管理请求,确保每次只有一个请求在执行。以下是一个简单的实现:

// 创建一个请求队列管理类
class RequestQueue {
  constructor() {
    this.queue = [];
    this.isProcessing = false;
  }

  // 添加请求到队列
  enqueue(requestFunc) {
    this.queue.push(requestFunc);
    this.processQueue();
  }

  // 处理队列中的请求
  async processQueue() {
    if (this.isProcessing || this.queue.length === 0) {
      return;
    }
    this.isProcessing = true;
    const requestFunc = this.queue.shift();
    try {
      await requestFunc();
    } catch (error) {
      console.error('Request failed:', error);
    } finally {
      this.isProcessing = false;
      this.processQueue();
    }
  }
}

// 实例化请求队列
const requestQueue = new RequestQueue();

// 示例请求函数
function makeRequest(url) {
  return () => uni.request({
    url: url,
    success: (res) => {
      console.log('Request succeeded:', res);
    },
    fail: (err) => {
      console.error('Request failed:', err);
    }
  });
}

// 添加请求到队列
requestQueue.enqueue(makeRequest('https://api.example.com/data'));

2. 使用节流(Throttle)或防抖(Debounce)

对于频繁触发的请求(如搜索框输入),可以使用节流或防抖技术来减少请求次数。以下是一个节流函数的示例:

function throttle(func, delay) {
  let lastTime = 0;
  return function(...args) {
    const now = new Date().getTime();
    if (now - lastTime >= delay) {
      lastTime = now;
      func.apply(this, args);
    }
  };
}

// 示例节流后的搜索函数
const throttledSearch = throttle(() => {
  uni.request({
    url: 'https://api.example.com/search',
    data: {
      query: searchInput.value
    },
    success: (res) => {
      console.log('Search results:', res);
    }
  });
}, 1000); // 1秒节流间隔

3. 服务器端优化

虽然前端可以采取措施减少请求阻塞,但服务器端优化同样重要。确保服务器端能够处理并发请求,并优化数据库查询和数据处理逻辑。

以上代码案例展示了如何在uni-app中通过请求队列管理和节流技术来避免接口请求阻塞。根据具体应用场景,可以选择合适的方案来优化请求处理。

回到顶部