在不用Promise的情况下如何控制异步请求?
如何更好的控制异步请求?相信大家一定首选Promise对象。确实,使用Promise控制异步请求确实非常方便,直接使用then()方法就可以实现当一个异步请求完成后再处理另一个请求或操作。同时,这样的代码也避免了使用大量的回调函数造成的“丑陋的代码”。
不过,在实际的工作中却总是不能尽人意。虽然es6越来越普及,但偶尔也会遇到一些维护老项目的情况,况且Promise的兼容性也是个问题......
恰好我今天也遇到了这个问题,不过情况更加复杂一些。简单描述一下就是——老项目有一个需求就是给一个游戏新增一个小结页,把原来老的小结页(写在iframe里)去掉。直接结果就是页面的按钮减少了,但事件数量不变,且都绑在了一个按钮上。这个按钮点击后意味着做完一道题,就要做一次异步请求来保存答案,然后判断是最后一题的话点击后会触发iframe的postMessage且切换页面,之后还有一次异步请求。由于全部是异步请求,这也直接导致了如果请求速度比较慢的话,页面先postMessage切换页面后,请求直接会shutdown掉!
所以要改的目的也很明确,就是当做到最后一题的时候,先执行完两个异步请求,最后再postMessage切换页面。老司机肯定都知道如果不能用Promise的话直接用回调函数就好了。不过这两个异步请求没有绑定在一起,所以想直接用回调函数也不是那么容易。我想了很久,实在搞不定,后来找leader,leader用一个巧妙的方法帮我搞定了。(我遇到的情况可能比较特殊,不过leader的这个思路确实非常棒)下面直接show给大家看!
$("#next").click(function(){ //每做完一题点击按钮保存
saveQuestion(title); //执行保存游戏的异步操作 if(....){
//执行一些操作
}; if(....){
//执行一些操作
}; if(game.over == true){ //当做到最后一题时会触发
postMessage(title); //iframe postMessage出去并切换页面,此时saveQuestion和saveTask没有完成请求的话会被shut down; saveTask(title); //执行第二个异步请求
} })
如果按照上述代码做的话请求会被关闭掉,原因我也说了,那么此时我们该如何做才能保证两个请求执行完再执行postMessage的操作呢?
$("#next").click(function(){
var flags = {
done:false
};
savaQuestiontitle, flags); if..... if..... if(game.over == true){
var showPostMessage = postMessage.bind(undefined,title);
var callback = function(flags,func){
while(flags.done == false){};
func();
}
callback = callback.bind(undefined,flags,postMessage);
saveTask(title,callback);
}
})
只要把代码写成这样就可以成功运行了!有的朋友可能看不懂,别急,我一句一句来分析!
首先先写一个flags对象,将flags作为参数传入异步请求的函数中,这个对象的作用主要用来控制异步请求的完成。只有当saveQuestion内的请求success或error后,将flags的done属性变为true;之后便是一系列if的判断,我们暂且省略;直到游戏结束时,我们声明一个回调函数callback ,这个回调函数传入两个参数,一个是flags对象,另一个是函数(即posMessaget);callback内部先是使用一个while循环,在flags.done为false时不停的循环,什么也不做。根据前面我们知道只有在saveQusetion异步请求结束后flags.done才会为true,所以说这个回调函数是为了控制saveQuestion的;
最后,我们再将回调函数放入saveTask中作为第二个参数,只有当saveTask请求结束后才调用callback!这样一来我们就可以保证整个程序先执行saveQuestion,虽然不知道saveQuestion什么时候请求结束,但可以通过flags.done来判断;之后执行saveTask,只有执行完saveTask后才会执行回调函数;如果此时saveQuestion请求还没结束,callback会在内部使用while等待请求,只有成功后才会执行最后的postMessage!
在不用Promise的情况下如何控制异步请求?的更多相关文章
- # Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析#
Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...
- 下一个ajax异步请求被挂起问题
异步请求按理来说应该是会不受其它ajax请求影响的,但如果是服务端访问了Session就不能这么说了. 了解了asp.net的会话管理,那我们来看看今天要谈到的主题: IReadOnlySession ...
- Chrome下解决本地异步请求失败的问题(Origin null is not allowed by Access-Control-Allow-Origin. )
Chrome更新版本后发现打开本地Jquery easyui没有数据,查看控制台才发现如下问题解决的办法是设置启动参数"--allow-file-access-from-files" ...
- 没有Promise的时候自己处理复合异步请求
function getList(options){ $.ajax(success:funciton(){ if(options.callback) options.callback.call(); ...
- 关于MySQL什么时候使用索引问题以及什么情况下应不建或少建索引
一,什么情况下使用索引1. 表的主关键字 自动建立唯一索引 2. 表的字段唯一约束 ORACLE利用索引来保证数据的完整性 3. 直接条件查询的字段 在SQL中用于条件约束的字段 如zl_yhjbqk ...
- @Java Web 程序员,我们一起给程序开个后门吧:让你在保留现场,服务不重启的情况下,执行我们的调试代码
一.前言 这篇算是类加载器的实战第五篇,前面几篇在这里,后续会持续写这方面的一些东西. 实战分析Tomcat的类加载器结构(使用Eclipse MAT验证) 还是Tomcat,关于类加载器的趣味实验 ...
- django后台使用MySQL情况下的事务控制详解
写在前面: 默认情况下django会把autocommit设置为“1”也就是说所针对数据库的每一次操作都会被做成“单独”的一个事务:这样的处理好处就在于它方便, 在编程的时候可以少写一些代码,比如我们 ...
- Oracle 无备份情况下的恢复--控制文件/数据文件
13.3无备份恢复控制文件 没有备份恢复控制文件其实就是在nomount状态,create control创建一个新的控制文件. dba必须知道4个信息才能正确的创建:数据库名.在线日志路径及其大小. ...
- DNS分别在什么情况下使用UDP和TCP
DNS同时占用UDP和TCP端口53是公认的,这种单个应用协议同时使用两种传输协议的情况在TCP/IP栈也算是个另类.但很少有人知道DNS分别在什么情况下使用这两种协议. 如果用wiresha ...
随机推荐
- CCIE-MPLS基础篇-实验手册
又一部前期JUSTECH(南京捷式泰)工程师职业发展系列丛书完整拷贝. MPLS(Multi-Protocol Label Switching) 目录 1:MPLS 基础实验.... 1.1实验拓扑. ...
- JS学习一
js中的变量输出 [使用JS的三种方式] 1. 在HTML标签中,直接内嵌JS(并不提倡使用): <button onclick="alert('你真点啊!')"> ...
- 201521123099《java程序设计》第五周学习总结
本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过?哪句会出现 ...
- 201521044152<java程序设计>第一周学习总结
本周学习总结 java开发时间虽然很短,但是发展迅速,已成为现在非常流行的一门语言,很开心能有幸学习java.第一周学习了java的平台,运行环境jdk以及jrt等等新名词,还了解了eclipse的基 ...
- 201521123060 《Java程序设计》第13周学习总结
1.本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 2.书面作业 1.网络基础 1.1比较ping www.baidu.com与ping cec.jmu.edu ...
- Jquery基础添加删除内容
直入主题,工作中比较常用的功能在input框内添加内容,不白话了,上代码! 布局: <div id="content"> <input type="te ...
- python只re模块
while True: phone_number=input('please input your phone number:') if len(phone_number)==11 \ and pho ...
- linux系统命令<二>----du的使用方法
1> 要显示一个目录树及其每个子树的磁盘使用情况 du /home/linux 这在/home/linux目录及其每个子目录中显示了磁盘块数. 2> 要通过以1024字节为单位显示一个目录 ...
- mybatis-basedao的实现
package com.yangwei.shop.dao; import java.util.HashMap; import java.util.List; import java.util.Map; ...
- java线程池相关知识点总结
Android中常见到的很多通用组件一般都离不开"池"的概念,如各种图片加载库,网络请求库,即使Android的消息传递机制中的Meaasge当使用Meaasge.obtain() ...