我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JavaScript前端超时异步操作的解决方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JavaScript前端超时异步操作的解决方法

今天就跟大家聊聊有关JavaScript前端超时异步操作的解决方法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

自从 ECMAScript 的 Promise ES2015 和 async/await ES2017 特性发布以后,异步在前端界已经成为特别常见的操作。异步代码和同步代码在处理问题顺序上会存在一些差别,编写异步代码需要拥有跟编写同步代码不同的“意识”。

如果一段代码久久不能执行完成,会怎么样?

如果这是同步代码,我们会看到一种叫做“无响应”的现象,或者通俗地说 —— “死掉了”;但是如果是一段异步代码呢?可能我们等不到结果,但别的代码仍在继续,就好像这件事情没有发生一般。

当然事情并不是真的没发生,只不过在不同的情况下会产生不同的现象。比如有加载动画的页面,看起来就是一直在加载;又比如应该进行数据更新的页面,看不到数据变化;

再比如一个对话框,怎么也关不掉 …… 这些现象我们统称为 BUG。但也有一些时候,某个异步操作过程并没有“回显”,它就默默地死在那里,没有人知道,待页面刷新之后,就连一点遗迹都不会留下。

Axios 自带超时处理

使用 Axios 进行 Web Api 调用就是一种常见的异步操作过程。通常我们的代码会这样写:

try {    const res = await axios.get(url, options);    // TODO 正常进行后续业务} catch(err) {    // TODO 进行容错处理,或者报错}

这段代码一般情况下都执行良好,直到有一天用户抱怨说:怎么等了半天没反应?

然后开发者意识到,由于服务器压力增大,这个请求已经很难瞬时响应了。考虑到用户的感受,加了一个 loading 动画:

try {    showLoading();    const res = await axios.get(url, options);    // TODO 正常业务} catch (err) {    // TODO 容错处理} finally {    hideLoading();}

然而有一天,有用户说:“我等了半个小时,居然一直在那转圈圈!”于是开发者意识到,由于某种原因,请求被卡死了,这种情况下应该重发请求,或者直接报告给用户 —— 嗯,得加个超时检查。

幸运的是 Axios 确实可以处理超时,只需要在 options 里添加一个 timeout: 3000 就能解决问题。如果超时,可以在 catch 块中检测并处理:

try {...}catch (err) {    if (err.isAxiosError && !err.response && err.request        && err.message.startsWith("timeout")) {        // 如果是 Axios 的 request 错误,并且消息是延时消息        // TODO 处理超时    }}finally {...}

Axios 没问题了,如果用 fetch() 呢?

处理 fetch() 超时

fetch() 自己不具备处理超时的能力,需要我们判断超时后通过 AbortController 来触发“取消”请求操作。

如果需要中断一个 fetch() 操作,只需从一个 AbortController 对象获取 signal,并将这个信号对象作为 fetch() 的选项传入。大概就是这样:

const ac = new AbortController();const { signal } = ac;fetch(url, { signal }).then(res => {    // TODO 处理业务}); // 1 秒后取消 fetch 操作setTimeout(() => ac.abort(), 1000);

ac.abort() 会向 signal 发送信号,触发它的 abort 事件,并将其 .aborted 属性置为 truefetch() 内部处理会利用这些信息中止掉请求。

上面这个示例演示了如何实现 fetch() 操作的超时处理。如果使用 await 的形式来处理,需要把 setTimeout(...) 放在 fetch(...) 之前:

const ac = new AbortController();const { signal } = ac;setTimeout(() => ac.abort(), 1000);const res = await fetch(url, { signal }).catch(() => undefined);

为了避免使用 try ... catch ... 来处理请求失败,这里在 fetch() 后加了一个 .catch(...) 在忽略错误的情况。如果发生错误,res 会被赋值为 undefined。实际的业务处理可能需要更合理的 catch() 处理来让 res 包含可识别的错误信息。

本来到这里就可以结束了,但是对每一个 fetch() 调用都写这么长一段代码,会显得很繁琐,不如封装一下:

async function fetchWithTimeout(timeout, resoure, init = {}) {    const ac = new AbortController();    const signal = ac.signal;    setTimeout(() => ac.abort(), timeout);    return fetch(resoure, { ...init, signal });}

没问题了吗?不,有问题。

如果我们在上述代码的 setTimeout(...) 里输出一条信息:

setTimeout(() => {    console.log("It's timeout");    ac.abort();}, timeout);

并且在调用的给一个足够的时间:

fetchWithTimeout(5000, url).then(res => console.log("success"));

我们会看到输出 success,并在 5 秒后看到输出 It's timeout

对了,我们虽然为 fetch(...) 处理了超时,但是并没有在 fetch(...) 成功的情况下干掉 timer。作为一个思维缜密的程序员,怎么能够犯这样的错误呢?干掉他!

async function fetchWithTimeout(timeout, resoure, init = {}) {    const ac = new AbortController();    const signal = ac.signal;        const timer = setTimeout(() => {        console.log("It's timeout");        return ac.abort();    }, timeout);        try {        return await fetch(resoure, { ...init, signal });    } finally {        clearTimeout(timer);    }}

完美!但问题还没结束。

万物皆可超时

Axios 和 fetch 都提供了中断异步操作的途径,但对于一个不具备 abort 能力的普通 Promise 来说,该怎么办?

对于这样的 Promise,我只能说,让他去吧,随便他去干到天荒地老 —— 反正我也没办法阻止。但生活总得继续,我不能一直等啊!

这种情况下我们可以把 setTimeout() 封装成一个 Promise,然后使用 Promise.race() 来实现“过时不候”:

race 是竞速的意思,所以 Promise.race() 的行为是不是很好理解?

function waitWithTimeout(promise, timeout, timeoutMessage = "timeout") {    let timer;    const timeoutPromise = new Promise((_, reject) => {        timer = setTimeout(() => reject(timeoutMessage), timeout);    });     return Promise.race([timeoutPromise, promise])        .finally(() => clearTimeout(timer));    // 别忘了清 timer}

可以写一个 Timeout 来模拟看看效果:

(async () => {    const business = new Promise(resolve => setTimeout(resolve, 1000 * 10));    try {        await waitWithTimeout(business, 1000);        console.log("[Success]");    } catch (err) {        console.log("[Error]", err);    // [Error] timeout    }})();

看完上述内容,你们对JavaScript前端超时异步操作的解决方法有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网行业资讯频道,感谢大家的支持。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JavaScript前端超时异步操作的解决方法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JavaScript前端超时异步操作的解决方法

今天就跟大家聊聊有关JavaScript前端超时异步操作的解决方法,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。自从 ECMAScript 的 Promise ES2015 和 as
2023-06-21

React Suspense前后端IO异步操作处理的方法

这篇文章主要讲解了“React Suspense前后端IO异步操作处理的方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“React Suspense前后端IO异步操作处理的方法”吧!简单介
2023-07-02

linux中pip操作时的超时解决方法

如何解决 linux 实例 pip 操作时的超时问题pip 是当前最流行的 python 安装包管理工具之一,很多阿里云用户会通过 pip 更新系统源。阿里云的 pip 源地址有以下三处: (默认)
2022-06-04

web前端:解决异步的几种实现方式

编程学习网: 异步双方不需要共同的时钟,也就是接收方不知道发送方什么时候发送,所以在发送的信息中就要有提示接收方开始接收的信息,如开始位,同时在结束时有停止位。
web前端:解决异步的几种实现方式
2024-04-23

springboot如何实现异步响应请求(前端请求超时的问题解决)

这篇文章主要给大家介绍了关于springboot如何实现异步响应请求(前端请求超时的问题解决)的相关资料,文中通过实例代码介绍的非常详细,对大家学习或者使用springboot具有一定的参考学习价值,需要的朋友可以参考下
2023-01-30

如何解决VPS服务器操作时卡的方法

如何解决VPS服务器操作时卡的方法,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。随着互联网的发展,许多企业或个人都开始用VPS搭建网站,但是在使用VPS服务器时
2023-06-05

32位操作系统不能认出超过4G内存的解决方法

编辑操作系统安装盘下boot.ini文件(隐藏文http://www.cppcns.com件),在[operating systems]的行后,加入/PAE,保存,重启系统后,就会认出超出4G的内存。如:[operating systems
2023-05-24

Win7运行应用程序时提示“非法操作”的原因和解决方法

提示“非法操作”通常是由以下几个原因引起的:1. 应用程序与操作系统不兼容:某些较旧或不受支持的应用程序可能无法在Windows 7上运行,尤其是在64位系统上。解决方法是尝试更新应用程序或找到一个与Windows 7兼容的替代程序。2.
2023-08-21

操作win8系统时遇到无法拖动桌面图标问题的解决方法

Windows8作为微软新推出的比较时尚的系统,受到了很多年轻用户的php喜欢,最为比较新的系统,在操作过程中遇到一些小问题在所难免,有些用户反应在操作win8系统的时候,碰到无法拖动桌面图标的情况,这时kGMJcYnpyf候该怎么办呢编程
2023-06-05

win10使用teambition软件时提示无权限操作资源的解决方法

小编给大家分享一下win10使用teambition软件时提示无权限操作资源的解决方法,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧! win10使用teambition软件时提示无权限操作资源怎么办1、点击左下角开始,在w
2023-06-10

使用U盘安装银河麒麟服务器操作系统V10SP2出现“设置基础软件仓库时出错”报错导致无法继续安装的解决方法

文章目录 一、复现步骤二、解决方法方法①:配置银河麒麟外网源(仅限于互联网环境)方法②:修改安装引导启动参数 一、复现步骤 操作系统版本:银河麒麟高级服务器操作系统V10SP2-20210524(x86_64) 使用Rufu
2023-08-22

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录