jq控制两个函数执行的前后顺序

您所在的位置:网站首页 jquery执行顺序 jq控制两个函数执行的前后顺序

jq控制两个函数执行的前后顺序

2024-07-17 00:24| 来源: 网络整理| 查看: 265

开篇先写中心:借助deferred对象,jq可自主控制不同函数之间执行顺序。

问题场景

经历过一些项目后,我们经常会遇到一类问题:有两个函数a和b,我们总是希望a函数运行成功后,再调用b函数,或者b函数中某个参数,需要用到a函数产生的数据,而不得不等待a函数执行结束,归根结底,我们需要的是a函数和b函数甚至c函数有限制好的执行顺序。

setTimeout():最初遇到这类问题,我可能会依赖于setTimeout()方法,但是用setTimeout改变函数执行顺序会出现很多问题,首先是时间设定,可能过短,导致顺序错乱,可能过长,导致函数执行时卡顿。其次当同一页面使用setTimeout过多,函数之间可能出现交叉、互相影响的现象,从而出现不可预料的bug。回调函数:回调函数是使用比较广泛的方式。因为本文的重点不在回调函数,而且这也不是一个友好的实现方式,回调地狱的大名在异步代码中如雷贯耳。不细究概念,从代码来看,可以简单列举两个例子: 一种是在异步代码的回调中,调用另一个异步。 $.ajax({ …… success:function(result){ $.ajax({ …… success:function(){ } }) } })

这段代码的意思是当一个ajax请求成功后,再执行另一个ajax请求,目的就是控制两个ajax的运行顺序,如果不在sucess回调中执行另一个ajax请求,两个ajax请求的先后顺序是无法保证的。 另一种是将函数作为参数传递给另一个函数。

function a(){ a的执行代码 } function b(a){ b的执行代码 a() } b()

当执行b函数时,会先执行b中的代码,然后再执行a()函数。其实很好理解,函数的参数可以是任何对象,基本的数据类型是对象,json是对象,函数也是对象,所以函数也是可以作为一个参数传递的。 关于回调函数的讲解可以查阅相应资料,个人认为这种类型的参数对于解决本文的问题是不可取的,但是对于理解函数很有帮助。

promise对象与deferred对象。 promise对象的概念很早就出现了,只不过ES6才将其写入标准语法,统一了用法,具体可参考阮一峰大神的ES6语法入门。 不过promise对象的思想很重要,但是具体实现个人认为,从代码应用角度来说,不需要深究,而应该使用更优雅的async。它有它的局限,就是即使我们可以用.then()的方式,用链式语法很优雅地执行异步语法,但是两个then()函数之间的数据传递,还是需要一个个抛出去给下一个方法,这种方式还是类似于回调函数传参的方式,具体内容可以将回调函数、promise都看一遍,就能发现其中函数之间传递参数时的相似之处。 总结一下,promise最大的好处是把形如回调地狱的一系列代码,改造成链式语法,至于原理,自行学习。 个人理解,deferred对象和promise对象的思想是一致的:deferred对象和promise对象中记录着事件操作的结果,当我得到某个结果后,手动的操作对象中的api,来更改对象的状态,从而来标识其中事件的状态。 在最近这次项目中,笔者使用了deferred对象,而不是promise对象主要考虑了两点: 1)deferred对象在jq 1.5版本之后就实现了,浏览器兼容性更好,目前在火狐42与谷歌55(或者56)均没有问题。 2)deferred对象不知可以操作异步函数,普通的js函数也可以操作。 代码示例: $.when(promiseUploadAvatar(file)).done(function () { ……逻辑代码 }) function promiseUploadAvatar() { var dfd = $.Deferred(); $.ajax({ type:'post', url: avatarImportUrl success:function (result) { ……逻辑代码 dfd.resolve(); }, error:function () { ……逻辑代码 dfd.reject(); } }); return dfd.promise() }

代码效果:等待异步操作promiseUploadAvatar()函数执行完毕后,才会执行.done()中的代码 代码解析:promiseUploadAvatar返回的是一个Deferred对象,dfd是实例化对象,dfd.promise()一定要和前面说的promise对象区别开,虽然有的地方也可能叫deferred的promise对象,但是和ES6中的promise并不是一回事。这是jq的defferred对象中自己封装的函数,可以理解为deferred promise对象,这个方法的作用是阻止其他代码来改变这个dfd对象,可以理解为这是deferred对象的只读版。 var dfd = $.Deferred();——实例化一个deferred对象,命名为dfd。 dfd.resolve()——告诉dfd对象,事件已经完成了,状态置为“已完成” dfd.reject()——告诉dfd对象,事件出问题了,状态置为“已失败” return dfd.promise()——把对象返回出去,当 $.when()调用时,告诉外面,这个事件究竟是什么情况,而 $.when()就是在等待dfd对象的状态,什么时候拿到dfd对象的状态了,什么时候执行后面的方法。 本例 $.when()后面的链式语法用的done(),意思是只要拿到dfd对象的状态是“已完成”,就会执行后面的代码,理论上,当状态置为“已失败”时,会执行.fail()中的代码。(但是在我这貌似没生效,因为用不到,所以也没有深究) deferred对象相关知识,推荐阮一峰deferred博客.



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3