在实际开发中常常遇到这样的问题:B函数中需要用到的变量或者参数,只有等A函数执行完毕了才能获取到。比如A函数中有一个ajax请求,而B函数中所需要的position变量需要在A函数中ajax请求完成才能得到它的准确值。
function A() { $.ajax({ url: '/api/test', type: 'POST', data: {...}, success: function(res) { position = res.position; } }) } function B() { $('.test').text(position); }
JavaScript的异步模式让B函数不会等待A函数计算出了position的值才会执行,它会不等待A函数的结果而直接开始执行,这样就会造成position无法正确赋值。为了解决这个问题,我们很容易想到使用回调函数,这也是最常用的方法之一
function A(callback) { $.ajax({ url: '/api/test', type: 'POST', data: {...}, success: function(res) { position = res.position; callback && callback(); } }) } function B() { $('.test').text(position); }
A函数有了回调之后,就可以将B函数当做回调函数传递给A
A(B);
可是如果这个时候,还有一个C函数,依赖于B的执行结果呢,后面甚至有可能出现一个D函数,依赖于C的结果!又如我们常用的ajax,成功了会有一个回调函数,失败了还有一个回调函数,面对这样复杂的情况,我们应该怎么样处理?虽然使用回调函数依然能够搞定这些烦人的难题,但是很显然这并不是一个好的解决办法。
jquery中的Deferred对象很好的解决了这个问题。在了解Deferred之前,我们可能需要了解一个JavaScript中的promise模式。当我们使用回调来解决实际中的问题时,很容易不知不觉中出现代码金字塔
step1(function() { step2(function() { step3(function() { step4(function() { step5(); }) }) }) })
假如这个时候有一个js库实现了promise模式,那么我们的代码就会变得清晰可读,并且每一步都会等待上一步执行完毕了才会执行。
new Promise().when(promiseStep1)
.then(promiseStep2)
.then(promiseStep3)
.then(promiseStep4)
.then(promiseStep5);
每一个promise对象都可以设置三种状态:
关于promise,还有更多需要了解的地方,我这里只是抛砖引玉。回到jQuery的Deferred对象来。jquery的Deferred对象就是对promise模式的一个很好的实现案例。我们通过一个简单的例子来看看Deferred对象应该如何使用。
函数first是一个耗时两秒的操作,而函数second是一个简单的函数,但是他需要在first执行完毕之后才执行。
function first() { setTimeout(function() { console.log('first'); }, 2000); } function second() { console.log('second'); } 为了达到second在first之后执行,使用Deferred对first函数做一个简单的处理即可 function first() { // 1 var defer = $.Deferred(); setTimeout(function() { console.log('first'); // 2 defer.resolve(); }, 2000); // 3 return defer.promise(); }
1、在函数中声明一个Deferred对象,这样在外部就无法修改函数内部的执行状态
2、函数执行完毕,设置执行状态,如果成功执行,defer.resolve(),如果执行失败,则设置为defer.reject()
3、在函数的最后,必须将deferred对象返回出去,否则外部无法得到函数的执行结果
在做了这样的处理之后,我们就可以满足要求的正常使用了
$.when(first())
.done(second());
jquery中,ajax方法就是使用promise模式完成的,我们可以看看常规写法和Deferred对象写法的不同。
// 常规写法 $.ajax({ url: '/api/test', type: 'POST', data: {...}, success: function(res) { // dosomething }, fail: function(res) { // dosomething }, complete: function() { // dosomething } }) // 新的写法 $.ajax({ url: '/api/test', type: 'POST', ... }) .done(function(res) { // success and do something }) .fail(function(res) { // fail and do something }) .always(function() {})
这个知识点差不多就总结完毕了。Promise模式与Deferred对象都还有更多值得了解知识点与用法,这是一个非常值得掌握的神兵利器,建议大家搜索更多的文章来学习它。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍jQuery的deferred对象使用详解,包括了jQuery的deferred对象使用详解的使用技巧和注意事项,需要的朋友参考一下 之前看别人的demo,发现在延迟对象被resolve时要执行的代码,有时会写在deferred.then方法里执行,有时会写在deferred.done方法里执行。 这让对延迟对象一知半解的我非常困惑,今天抽时间研究了一下下,发现:在某种环境下,两个方
本文向大家介绍jQuery中deferred对象使用方法详解,包括了jQuery中deferred对象使用方法详解的使用技巧和注意事项,需要的朋友参考一下 在jquery1.5之后的版本中,加入了一个deferred对象,也就是延迟对象,用来处理未来某一时间点发生的回调函数。同时,还改写了ajax方法,现在的ajax方法返回的是一个deferred对象。 那就来看看deferred对象的用法。 1
Boost.Bind Bind是对标准库的绑定器bind1st 和 bind2nd的泛化。这个库支持使用统一的语法将参数绑定到任何类似于函数行为的东西,如函数指针、函数对象,以及成员函数指针。它还可以通过嵌套绑定器实现函数组合。这个库不要求那些对标准库绑定器的强制约束,最显著的就是不要求你的类提供typedefs result_type, first_argument_type, 和 second
初学 Python 时可能不适应需要手动注释文件编码的写法,根据 PEP 263 所定义, 必须在 Python 文件的前两行,按照下面的写法注明文件的编码: # coding=<encoding name> 或者: # -*- coding: <encoding name> -*- 或者: # vim: set fileencoding=<encoding name> : 如果不定义文件的
本文向大家介绍JavaScript原型对象原理与应用分析,包括了JavaScript原型对象原理与应用分析的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了JavaScript原型对象原理与应用。分享给大家供大家参考,具体如下: 原型对象: 每个对象都有一个参考对象,这个参考对象称之为原型对象。原型对象有自己的属性和方法。当A是B的原型对象时,那么B拥有A中的所有属性和方法。 原型对象的工作
本文向大家介绍jQuery中的pushStack实现原理和应用实例,包括了jQuery中的pushStack实现原理和应用实例的使用技巧和注意事项,需要的朋友参考一下 pushStack是jQuery内核中一个非常重要的函数,它是如此重要,以至于许多jQuery内部函数中都频繁用到它。平常情况下,虽然很少用到它, 但是掌握这个函数,不仅有利于理解jQuery的运行原理,还方便我们做更加高级的jQu
本文向大家介绍Java switch使用原理及实例解析,包括了Java switch使用原理及实例解析的使用技巧和注意事项,需要的朋友参考一下 这篇文章主要介绍了Java switch使用及实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java中有两个经常用于条件判断的方法,一个是if{}else{},另一个就是switch()了。总的
本文向大家介绍.net面向对象之多线程(Multithreading)及 多线程高级应用,包括了.net面向对象之多线程(Multithreading)及 多线程高级应用的使用技巧和注意事项,需要的朋友参考一下 在.net面向对象程序设计阶段在线程资源共享中的线程安全和线程冲突的解决方案;多线程同步,使用线程锁和线程通知实现线程同步,具体内容介绍如下: 1、 ThreadStatic特性 特性:[