jquery高级应用之deferred对象 - 编程思维

在实际开发中常常遇到这样的问题: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对象都可以设置三种状态:

pending  [进行中]
resolve  [已经正确执行]
reject   [执行失败]

关于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对象都还有更多值得了解知识点与用法,这是一个非常值得掌握的神兵利器,建议大家搜索更多的文章来学习它。

版权声明:本文版权归作者所有,遵循 CC 4.0 BY-SA 许可协议, 转载请注明原文链接
https://segmentfault.com/a/1190000005607968

yii2 增删改查后仍留在当前页的方法 - 编程思维

序言 实现增删改查操作成功后仍留在当前页,能给用户一个良好的体验。但是 Yii2 框架本身是没有在增删改查操作成功后仍留在当前页的效果的,要实现这样的一个效果得自己写。我的原则是不动核心代码,始终坚持自己的原则,现实现了我把它分享出来。殊途同归,如有更好的实现方法,欢迎交流。 需求分析 1、实现增删改查后操作成功后仍然

正在暑假中的《课多周刊》(第1期) - 编程思维

正在暑假中的《课多周刊》(第1期) 我们的微信公众号:fed-talk,更多精彩内容皆在微信公众号,欢迎关注。 若有帮助,请把 课多周刊 推荐给你的朋友,你的支持是我们最大的动力。 远上寒山石径斜,白云深处有人家。停车坐爱枫林晚,霜叶红于二月花。 杜牧 -《山行》 HTML/CSS 【译】22个必备的CSS小技巧(@

【转】理解css模块化 - 编程思维

原文链接: https://www.sitepoint.com/und... 在瞬息万变的前端开发世界中,很难找到一个真正有意义的概念,并且将其清晰明了的向广大人民群众普及。 把目光投向CSS,一个重大转折就是CSS预处理器的出现(在工具方面来看),其中, Sass应该是最为著名的一个。此外,还有 PostCSS,它和

玩转react样式 - 编程思维

很久很久以前,就有人用CSS来时给HTML内容添加样式。CSS可以最大限度的分离样式和内容,选择器也可以很方便的给某些元素添加样式。你根本找不到任何不用CSS的理由。 但是在React这里就是另外一回事了,虽然React不是不用CSS。但是,它在给元素添加样式的时候方式不同。React的核心哲学之一就是让可视化的组件自

零react基础入门amaze ui touch! - 编程思维

全文的目的是达成使用amazeui-touch进行项目开发,并且以我这个前端菜鸟所见所学来归纳整理。文章不对详细内容做讲解。 环境安装与前期准备 我的基础环境: Win10 ATOM : GitHub出的开源的编辑器 CMDER : http://cmder.net/ 命令行工具, windows下一个炒鸡好用的神

全面解析yii2跨域的sso登录逻辑 - 编程思维

简述 本文章是我对Yii2如何实现SSO登录做一个全面的逻辑解析。事实上,在此之前我也写过两篇文章关于SSO登录的实现方式以及进一步优化,包括这篇文章也都是介绍Yii2的SSO登录,逐步优化不断总结与分享,目的就是要把Yii2的SSO登录功能尽可能的做到极致,从程序开发的灵活性角度去思考问题,把一切潜在的局限扼杀在摇篮

yii2 增删改查后仍留在当前页的方法 - 编程思维

序言 实现增删改查操作成功后仍留在当前页,能给用户一个良好的体验。但是 Yii2 框架本身是没有在增删改查操作成功后仍留在当前页的效果的,要实现这样的一个效果得自己写。我的原则是不动核心代码,始终坚持自己的原则,现实现了我把它分享出来。殊途同归,如有更好的实现方法,欢迎交流。 需求分析 1、实现增删改查后操作成功后仍然

安装elasticsearch初体验 - 编程思维

今日项目需要一个小型的搜索的功能的支持,有很多开源的搜索引擎啦,当然Elasticsearch个人认为上手容易,安装也比较方便。 ES安装前需要确认你笔记本上已经安装了java,如果没有安装了,可以oracle官网下载就行了, java弄完后,我们可以在命令后工具中输入java -version查看版本信息 安装El

yii2 验证手机号、邮箱唯一性 - 编程思维

序言 验证唯一性很重要,说不上用得很普及,但是也必须要有。好比注册功能模块,手机号、邮箱注册这些,肯定是要验证其的唯一性的,重复了登录就会混乱。那么如何使用Yii2自带的targetClass验证唯一性呢?使页面刷新的可能很多人都会,要是不刷新页面直接触发targetClass验证的应该就少些了吧!不会的也不必苦恼,不

restfual api 架构的第三方登录 - 编程思维

序言 第三方登录的使用在当今非常普遍,不管是PC端还是手机端都很常见。因为它有着一号多用的特点,不管是在什么网站什么软件上只要有了这个第三方登录的功能就无需再次走注册步骤,直接用第三方的账号登录就可以了,方便吧?开发程序看重的是用户体验,为用户打造一款“麻雀虽小,五脏俱全”,使用便利的产品是我们的职责。那么话又说回来,

mysql必知必会(5):计算字段的使用 - 编程思维

本文主要介绍Mysql中计算字段的使用方法 我博客文章地址:http://weiya.me/item/60.html 简介 在创建数据库表的时候,往往为了数据库的各种性能,我们需要将字段拆分或者按照特定的类型存储。而在读取数据库的时候,检索出来的数据往往不是我们直接需要使用的数据。举几个例子: 我们在存储省市区和街道