热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

利用promise实现一个超时请求处理

今天面试官问的我这个问题,说实话,我当时懵逼了。我第一个想法竟然是:嘶~这问题挺简单的啊,不就是用Date对象判断是否大于某

今天面试官问的我这个问题,说实话,我当时懵逼了。
我第一个想法竟然是:嘶~这问题挺简单的啊,不就是用 Date 对象判断是否大于某个时间差么?于是写出了下面这段代码:

let rest=function(){// 开始是放在外面的,但是面试官说要尽可能不单独暴露值,于是鬼迷心窍(紧张)杀都没想就直接扔进来了...let date=Date.now();return new Promise((resolve,reject)=>{let _date=Date.now();if(_date-date>2000){reject('请求超时');}resolve();})
}

在我暗自得意是不是快结束了面试官一会儿会如何告诉我面试通过了的时候,对面突然传来一句话:
“你这个,确定要这样?”
“你这样if条件真的会执行么?”
what!
我顿时感觉大事不妙大惊失色,正要仔细看时面试官已经说出了“行吧,这道题你再想想,这次的面试就到这里吧”

下来后仔细想想,“基于promise”的前提就已经提示了应该要“尽可能地应用promise的特性”,那么,这个问题应该用什么呢?

我想起了前两天写过的这篇文章:实现一个“能中断的”ajax 。里面提到了可以用 “ reject抢跑 ”的方法去中止后续回调的执行!


这里要记得一点:promise状态值改变一旦触发就不可逆,所以不可能真正“中断”promise,只能说通过同步与异步的先后规则(event Loop)去让“成功”的回调无法执行。


我似乎恍然大悟了起来…

但现在还有一个问题:怎么判断“超时”?
如果不出意外,你把两个 Date 放在一个函数中无论如何它们的值都是相同的!所以我想到了 setTimeout !有了这个异步时间处理,我的思路就明朗了起来:在promise中有一个API叫:Promise.race() ,和 all() 不同的是,race在其中promise状态值有一个改变时就会立刻执行它的结果,就像这样:

let rest=function(_data=1000){return Promise.race([upload().then(data=>{console.log(data.data)}),uploadTimeout(_data)])
}
function upload(){console.log(&#39;请求进行中...&#39;);return new Promise((resolve,reject)&#61;>{let xhr&#61;new XMLHttpRequest();xhr.open(&#39;GET&#39;,"https://devapi.qweather.com/v7/weather/24h?location&#61;这里是纬度和经度英文逗号分搁&key&#61;这里是百度地图的key");xhr.onload&#61;function(){if(xhr.readyState&#61;&#61;4 && (xhr.status>&#61;200 && xhr.status<300)){setTimeout(()&#61;>{resolve({data:JSON.parse(xhr.responseText)})},2000)}else{reject(xhr.status)}}xhr.onerror&#61;function(){reject(&#39;请求失败了...&#39;)}xhr.send(null);// 【1】})
};
function uploadTimeout(times){return new Promise((resolve,reject)&#61;>{setTimeout(()&#61;>{reject(&#39;请求超时&#xff0c;请重试&#39;); // 【2】},times)})
}

到这里&#xff0c;基本实现了功能&#xff0c;但是运行后你会发现&#xff1a;第一个函数在报错后仍然执行了&#xff01;
对&#xff0c;这就是上面说的&#xff1a;promise状态值改变的过程是不可逆的。而且虽然你下面返回了reject&#xff0c;但是这是两个promise&#xff0c;之间是不冲突的&#xff01;

受上面说过的 reject抢跑 的启发&#xff0c;我们可以在代码中标注为【1】的地方写这样的代码&#xff1a;

// 向外暴露取消函数
cancelFn&#61;function(msg){reject(&#39;请求超时&#xff0c;请重试&#39;);
}

然后将代码中标注为【2】的地方的代码替换为&#xff1a;

cancelFn();

至此&#xff0c;一个“超时请求处理”的功能就真的实现了&#xff1a;
view


推荐阅读
  • 使用 jQuery 实现页面加载进度条
    页面加载进度条是提升用户体验的重要工具,通过在页面头部显示一个加载状态,并在页面完全加载后隐藏,可以有效减少用户的等待焦虑。本文将详细介绍如何使用 jQuery 实现这一功能。 ... [详细]
  • 本文探讨了异步编程的发展历程,从最初的AJAX异步回调到现代的Promise、Generator+Co以及Async/Await等技术。文章详细分析了Promise的工作原理及其源码实现,帮助开发者更好地理解和使用这一重要工具。 ... [详细]
  • 理解浏览器历史记录(2)hashchange、pushState
    阅读目录1.hashchange2.pushState本文也是一篇基础文章。继上文之后,本打算去研究pushState,偶然在一些信息中发现了锚点变 ... [详细]
  • 在现代Web开发中,HTML5 Canvas常用于图像处理和绘图任务。本文将详细介绍如何将Canvas中的图像导出并上传至服务器,适用于拼图、图片编辑等场景。 ... [详细]
  • ABP框架是ASP.NET Boilerplate的简称,它不仅是一个开源且文档丰富的应用程序框架,还提供了一套基于领域驱动设计(DDD)的最佳实践架构模型。本文将详细介绍ABP框架的特点、项目结构及其在Web API优先架构中的应用。 ... [详细]
  • 本文探讨了如何利用RxJS库在AngularJS应用中实现对用户单击和拖动操作的精确区分,特别是在调整区域大小的场景下。 ... [详细]
  • 本文探讨了如何通过优化 DOM 操作来提升 JavaScript 的性能,包括使用 `createElement` 函数、动画元素、理解重绘事件及处理鼠标滚动事件等关键主题。 ... [详细]
  • Android与JUnit集成测试实践
    本文探讨了如何在Android项目中集成JUnit进行单元测试,并详细介绍了修改AndroidManifest.xml文件以支持测试的方法。 ... [详细]
  • 深入理解:AJAX学习指南
    本文详细探讨了AJAX的基本概念、工作原理及其在现代Web开发中的应用,旨在为初学者提供全面的学习资料。 ... [详细]
  • HTML:  将文件拖拽到此区域 ... [详细]
  • 本文介绍了如何通过 XMLHttpRequest 对象在不同浏览器中实现 AJAX 的 POST 和 GET 请求,并详细说明了 XMLHttpRequest 的五个状态及其含义。 ... [详细]
  • 文章目录python包-requests关于requests包安装和使用pythonrequests请求超时设置工作中遇到的常见问题整理访问https网站,报错cer ... [详细]
  • 深入理解Java多线程与并发机制
    本文探讨了Java多线程和并发机制的核心概念,包括多线程类的分类、执行器框架、并发容器及控制工具。通过详细解析这些组件,帮助开发者更好地理解和应用多线程技术。 ... [详细]
  • 本文介绍了如何使用Node.js通过两种不同的方法连接MongoDB数据库,包括使用MongoClient对象和连接字符串的方法。每种方法都有其特点和适用场景,适合不同需求的开发者。 ... [详细]
  • 电商高并发解决方案详解
    本文以京东为例,详细探讨了电商中常见的高并发解决方案,包括多级缓存和Nginx限流技术,旨在帮助读者更好地理解和应用这些技术。 ... [详细]
author-avatar
工农大路店NOKIA客户服务中心
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有