【小程序-慕尚花坊04】网络请求并发与loading

网络请求并发与loading

  • 一,网络请求并发与loading
    • 1,并发处理
      • 1.1,异步实现方式
      • 2.2,Promise.all异步方式封装
    • 2,loading加载
      • 2.1,loading的基本使用
      • 2.2,loading与并发结合案例
      • 2.3,loading控制
    • 3,并发配合loading完整代码

如需转载,请附上链接https://blog.csdn.net/m0_59269218/article/details/151002956

一,网络请求并发与loading

一,网络请封装-响应拦截器
本篇文章依旧是慕尚花坊的初始化篇网络请求拦截器的封装,本文主要讲解的是网络请求的并发处理,以及对loading的封装。由于这篇文章要写的内容是基于前两篇内容的,因此可以先看前两篇文章或者直接拉去gitee残酷代码即可

在学习本系列之前,再次先提供一下尚硅谷给的接口文档和笔记资料,以及自己的仓库地址

接口文档:https://s.apifox.cn/6ed6c5c4-56c4-4619-8e2a-4817aa140e30
笔记资料:https://www.yuque.com/bigweb/dpa5f7/dm2ygniwxksuxy6o
学习视频对应链接:https://www.bilibili.com/video/BV1LF4m1E7kB
本系列个人的gitee仓库地址:https://gitee.com/zhenghuisheng/mu-shanghua-fang

1,并发处理

1.1,异步实现方式

并发处理一般指的是服务器同时接收到多个请求的处理,前端的并发请求指的是同一时间向后端发起多个请求,比如打开某个页面时,需要同时的拿后端多个数据的列表,那么这些请求之间就是并发关系

实现异步的方式主要有两种,一种是直接通过async+await的方式实现异步,一种是直接通过Promise.all的方式实现异步。如果两个是发起单个请求,二者区别不大,如果是发起多个异步请求,那么二者之间就会存在差异

如果直接使用async+await 的方式实现异步,其案例如下,那么在多个并发请求时使用这种方式,由于每个请求需要等待结果返回,那么就会造成请求的阻塞,需要上一个请求那道结果之后,才能继续进行下一个请求,由于阻塞的原因,又相当于将异步变成了同步

  async sendRequest() {await instance.get("/index/findBanner")await instance.get("/index/findCategory1")await instance.get("/index/findBanner")await instance.get("/index/findCategory1")}

点击请求之后,可以发现四个请求依次执行的,需要等上一次请求完成之后再完成下一个请求,因此在多个请求的并发处理场景方面,其效率不高,结合Time和Waterfall两个相应参数可以看出这四个请求需要花费的时间为 233+93+94+91=511ms

在这里插入图片描述

接下来看第二种异步请求方式,通过 Promise.all 的方式实现异步请求,其案例如下,直接将请求丢到数组里面即可

await Promise.all([instance.get("/index/findBanner"),instance.get("/index/findCategory1"),instance.get("/index/findBanner"),instance.get("/index/findCategory1")])

点击请求之后,其相应如下,结合Waterfall和Time可以看出,总共花费就是最大的那个时间,总共花费333ms,比上面的511ms效率快了很多。

在这里插入图片描述

2.2,Promise.all异步方式封装

经过测试,可以发现Promise.all的异步请求方式是高于asyns+await的方式的,因此后续的异步方式同意通过这个Promise.all的方式进行异步调用。

那么只需要在request.js文件中,封装一个全局使用的异步请求即可,其代码如下

// 封装一个异步处理请求
all(...promise){return Promise.all(promise)
}

那么在这个test.js文件中,直接使用这个全局封装的异步处理即可

import instance from '../../utils/request'
Page({// 点击按钮触发 handler 方法async sendRequest() {// 方式三await instance.all(instance.get("/index/findBanner"),instance.get("/index/findCategory1"),instance.get("/index/findBanner"),instance.get("/index/findCategory1"))}
})

2,loading加载

2.1,loading的基本使用

在项目开发中,在列表渲染前调用后端的列表接口一般都需要通过loading加载一会,比如下拉刷新等,因此也可以在这个request.js文件中最这个loading进行封装,其思路如下,在请求发送前开始加载loading,在想要结束之后关闭这个loading

// 服务发送之前,添加loading效果
wx.showLoading()
// 服务器响应后,隐藏loading效果
complete: () => {wx.hideLoading()
}

2.2,loading与并发结合案例

如果在并发请求中需要展示和关闭loading,那么就可能出现前一个以及展示完的loading会把后面要展示的loading给关闭了,或者说后面请求的loading先执行完将前面的请求loading给覆盖了的情况,或者可能出现闪烁的问题。

那么为了解决这种并发的问题,可以直接通过队列的方式来进行解决,其核心代码如下,新增一个queue队列,让后在请求前往队列中push一个request字符串

// 定义 constructor 构造函数,用于创建和初始化类的属性和方法
constructor(params = {}) {...// 初始化数组this.queue = []
}

在发送请求之前判断队列长度是否为0,为0就开启loading,并且往队列中push一个字符串

// 发送请求之前添加 loding
this.queue.length === 0 && wx.showLoading()
// 然后想队列中添加 request 标识,代表需要发送一次新请求
this.queue.push('request')

在响应回调后再判断队列是否为空,并且在每个complete回调中需要设置一个定时器,并且在完成之后需要将删除

complete: () => {// 每次请求结束后,从队列中删除一个请求标识this.queue.pop()// 如果队列已经清空,在往队列中添加一个标识this.queue.length === 0 && this.queue.push('request')// 等所有的任务执行完以后,经过 100 毫秒// 将最后一个 request 清除,然后隐藏 loadingthis.timerId = setTimeout(() => {this.queue.pop()this.queue.length === 0 && wx.hideLoading()}, 100)
}

2.3,loading控制

上面是在全局的js文件中使用了loading的加载,也就是说不管外部想不想用这个loading,发起请求时都会进行这个loading的加载,为了解决这个问题,可以将这个选择控制权交给外部自定义,如果外部不定义也可以给一个默认参数进行全局控制,比如默认就是打开loading的加载和关闭

首先是在 WxRequest 类的defaults属性中,增加一个isLoading的属性,给默认值为true

class WxRequest {// 初始化默认的请求属性defaults = {isLoading: true // 是否显示 loading 提示框}
}

如果外部不想使用这个isLoading,那么在外部初始化这个对象的时候,可以对这个参数进行值的设置

// 对 WxRequest 进行实例化
const instance = new WxRequest({baseURL: 'https://gmall-prod.atguigu.cn/mall-api',isLoading: false // 隐藏 loading
})

那么在使用loading的时候,又需要判断是否需要使用loading,需要的话再操作队列

// 发送请求之前添加 loding
if (options.isLoading) {this.queue.length === 0 && wx.showLoading()// 然后想队列中添加 request 标识,代表需要发送一次新请求this.queue.push('request')
}

在complete回调中,也需要判断是否需要使用loading,如果不需要则直接提前返回

complete: () => {if (!options.isLoading) return
}        

3,并发配合loading完整代码

在request.js文件中的全部代码如下,增加了并发控制和loading,并且对并发控制和loading进行了结合使用,loading的控制权也可以交给外部自行控制和定义

class WxRequest {//url表示请求的接口,data表示query的参数,method表示请求的方法,config表示需要覆盖的默认参数get(url, data = {}, config = {}) {return this.request(Object.assign({url,data,method: "GET"}, config))}// 封装 POST 实例方法post(url, data = {}, config = {}) {return this.request(Object.assign({url,data,method: 'POST'}, config))}// 封装 PUT 实例方法put(url, data = {}, config = {}) {return this.request(Object.assign({url,data,method: 'PUT'}, config))}// 封装 DELETE 实例方法delete(url, data = {}, config = {}) {return this.request(Object.assign({url,data,method: 'DELETE'}, config))}// 定义默认拦截器interceptors = {// 请求拦截器request: (config) => config,// 响应拦截器response: (response) => response}// 全局异步处理all(...promise) {return Promise.all(promise)}// 默认参数对象defaults = {baseURL: '', // 请求基准地址url: '', // 开发者服务器接口地址data: null, // 请求参数method: 'GET', // 默认请求方法header: { // 请求头'Content-type': 'application/json' // 设置数据的交互格式},timeout: 60000, // 小程序默认超时时间是 60000,一分钟,isLoading: true // 是否显示 loading 提示框}// 定义 constructor 构造函数,用于创建和初始化类的属性和方法constructor(params = {}) {// 在实例化时传入的参数能够被 constructor 进行接收console.log(params)// 使用 Object.assign 合并默认参数以及传递的请求参数this.defaults = Object.assign({}, this.defaults, params)// 初始化数组this.queue = []}/*** @description 发起请求的方法* @param { Object} options 请求配置选项,同 wx.request 请求配置选项* @returns Promise*/request(options) {// 拼接完整的请求地址options.url = this.defaults.baseURL + options.url// 合并请求参数options = {...this.defaults,...options}// 服务器发送之前调用请求拦截器options = this.interceptors.request(options)if (options.isLoading) {// 发送请求之前添加 lodingthis.queue.length === 0 && wx.showLoading()// 然后想队列中添加 request 标识,代表需要发送一次新请求this.queue.push('request')}// 使用 Promise 封装异步请求return new Promise((resolve, reject) => {// 使用 wx.request 发起请求wx.request({...options,// 接口调用成功的回调函数success: (res) => {// 合并请求参数和响应参数,方便调试const mergrRes = Object.assign({}, res, { config: options, isSuccess: true });// 响应后调用响应拦截器resolve(this.interceptors.response(mergrRes))},// 接口调用失败的回调函数fail: (err) => {// 合并请求参数和响应参数,方便调试const mergrErr = Object.assign({}, err, { config: options, isSuccess: false });// 响应后调用响应拦截器reject(this.interceptors.response(mergrErr))},complete: () => {// 如果不展示,则直接返回if (!options.isLoading) return// 每次请求结束后,从队列中删除一个请求标识this.queue.pop()// 如果队列已经清空,在往队列中添加一个标识this.queue.length === 0 && this.queue.push('request')// 等所有的任务执行完以后,经过 100 毫秒// 将最后一个 request 清除,然后隐藏 loadingthis.timerId = setTimeout(() => {this.queue.pop()this.queue.length === 0 && wx.hideLoading()}, 100)}})})}
}
// 将 WxRequest 的实例通过模块化的方式暴露出去
export default WxRequest

可以在http.js中的isLoading设置成false来进行测试,直接将isLoading设置成false

const instance = new WxRequest({baseURL: 'https://gmall-prod.atguigu.cn/mall-api',timeout: 15000,isLoading: false
})

或者也可以直接在请求这里直接设置isLoading的值,比如在test.js文件的请求中,设置isLoading的值为false


import instance from '../../utils/http'
Page({// 点击按钮触发 handler 方法async handler() {await instance.all(instance.get("/index/findBanner",{},{isLoading:false}))}
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/95044.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/95044.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS 7 升级 OpenSSH 10.0p2 完整教程(含 Telnet 备份)

🔹 CentOS 7 升级 OpenSSH 10.0p2 完整教程(含 Telnet 备份) 注意:为了避免升级 SSH 时无法远程登录,建议先启用 Telnet 服务 作为备用连接方式。 CentOS 7 默认 OpenSSH 版本是 7.x,升级到 10.0p2 需要 源…

aragfw9.dll aqnky-ef.dll aqua dock.dll apscon~1.dll apropdll.dll app_web_yqnqasrp.dll app_web_

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…

rabbitMQ延时队列实现,怎么保证消息的幂等

一、RabbitMQ 延时队列实现方式 基于 TTL(Time-To-Live) 死信队列(Dead Letter Queue) 这是最常用的实现方式,核心思路是: (1)消息设置过期时间(TTL) (2)消息过期后进入绑定的死信队…

前沿技术观察:从AI 时代到量子计算的下一站

前沿技术观察:从AI 时代到量子计算的下一站🚀 技术的浪潮一波接一波,从 人工智能 到 区块链,再到 边缘计算、元宇宙、量子计算,这些前沿技术正在深刻影响我们的生活与产业格局。 对于开发者和技术爱好者来说&#xff0…

通过Kubernetes安装mysql5服务

以下是清晰、结构化的操作流程优化说明,按步骤梳理从部署到配置持久化、暴露服务的完整过程:一、基础部署:快速验证 MySQL 可用性创建有状态工作负载进入 KubeSphere 项目 → 工作负载 → 有状态副本集 → 创建,选择 通过镜像创建…

【mysql】SQL 中 IS 与 = 的区别:一个 NULL 值引发的思考

SQL 中 IS 与 的区别:一个 NULL 值引发的思考为什么查询结果总是少一条数据?可能是 NULL 在捣鬼在 SQL 查询中,很多开发者都曾遇到过这样的困惑:明明看起来正确的查询语句,返回的结果却总是与预期不符。这往往是因为没…

openGauss笔记

1、安装 直接用docker安装 2、国产化 符合国产化要求 3、客户端 3.1 dbeaver 社区版本(25.1.4)即可,驱动建议用离线版本,在官网下载最新的,然后在驱动管理里面进行添加本地的jar 3.1.1 驱动配置3.1.2 依赖 需要java版本…

SQL语言增删改查之C与R

本节通关要求1、掌握 SQL 语句对数据库进行的创建 Create 和读取 Retireve 操作的指令;2、多练习🎮说明:操作对象是数据表中的数据行,也就是表中的记录。请明确操作对象,不要误伤友军。背景:create table i…

栈溢出问题

brpc 的 bthread 默认协程栈大小是 128KB(非 pthread 模式)。如果在一个bthread中,它执行的函数内定义了一个局部变量map,有很多个元素,map的大小超过了128KB,协程会自动申请新的栈空间吗?这里要…

Android之穿山甲广告接入

文章目录前言一、效果图二、实现步骤1.引入库2.build.gradle依赖3.Application初始化3.开屏广告4.插屏广告5.懒人做法总结前言 项目接入广告已经是常见的现象了,但是还有很多朋友或者初学者没有接触过,或者没有接触过穿山甲,今天就来看一下&…

Web开发工具一套式部署Maven/Nvm/Mysql/Redis

前言: 对于一个纯小白且电脑没有任何环境的计算机学生,如何快速跑通Java前后端项目呢? 先附上百度网盘 地址: Web开发工具 。 以下链接来自不同作者,如有侵犯,请联系我删除。 1.Jdk 部署地址&#xff1a…

Deepseek法务提示指令收集

参考网络资料,收集一些法务提示指令,可用于Agent LLM、以及LLM法律相关开发。 https://zhuanlan.zhihu.com/p/22588251815 1 基础指令 1) 身份认证模块 【身份与版本声明】 您是由DeepSeek研发的法律智能辅助系统V4.2版,内核经司法部《生成…

Tiptrans转运 | 免费5国转运地址

Tiptrans 是一家总部位于捷克的国际包裹转运与虚拟地址服务平台,主要提供全球虚拟收货地址(英国、德国、香港、美国等),让用户在当地网店购物,再由 Tiptrans 转运到海外。除了物流服务,Tiptrans 也提供虚拟…

STM32手动移植FreeRTOS

📦 准备工作 获取FreeRTOS源码: 访问 FreeRTOS官网 或其 GitHub仓库 下载最新版内核源码。 你也可以使用Git克隆(注意要包含子模块):git clone https://github.com/FreeRTOS/FreeRTOS.git --recurse-submodules。 准备STM32基础…

C5仅支持20MHZ带宽,如果路由器5Gwifi处于40MHZ带宽信道时,会出现配网失败

是的,这会导致“怎么都连不上”。结论先说:如果路由器把 5 GHz 固定在 40 MHz(或以上)带宽,而你的 C5 只支持 5 GHz 的 20 MHz 带宽,那么 STA 连接一定会失败。固件里不可能“把 40 MHz AP 连成 20 MHz”&a…

坚鹏请教DEEPSEEK:请问中国领先的AI智能体服务商有哪些?知行学

坚鹏请教DEEPSEEK:请问中国领先的AI智能体服务商有哪些?深圳知行学教育科技公司名列榜首根据2025年8月底多家权威机构发布的榜单和报告,比如德本咨询(DBC)的“2025企业级AI Agent应用TOP50”榜单、IDC的《中国AI AGENT…

【开题答辩全过程】以 投票系统为例,包含答辩的问题和答案

个人简介一名14年经验的资深毕设内行人,语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧。感谢大家的…

C++异常处理指南:构建健壮程序的错误处理机制

在程序开发的世界里,“错误” 是绕不开的话题。你可能写过一个简单的计算器,却因为用户输入 “50” 而崩溃;也可能在操作数据库时,因为权限不足导致数据读取失败;甚至在申请内存时,因为系统资源耗尽而无法继…

comfUI背后的技术——VAE

第一次知道VAE可能还是许嵩。当然,这里的VAE指的是变分自编码器(Variational Autoencoder, VAE) Seq2Seq 在 Seq2Seq 框架提出之前,深度神经网络在图像分类等问题上取得了非常好的效果。在其擅长解决的问题中,输入和…

【序列晋升】21 Spring Cloud Gateway 云原生网关演进之路

Spring Cloud Gateway作为Spring生态系统中的核心组件,已成为微服务架构中的首选API网关解决方案。它基于响应式编程模型,提供高性能、可扩展的路由管理和跨领域功能,解决了传统微服务架构中的接口聚合、安全管控和流量控制等核心问题。与此同…