经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » jQuery » 查看文章
jQuery(五): Deferred
来源:cnblogs  作者:xy2370  时间:2019/9/12 9:10:54  对本文有异议

jQuery(五): Deferred

有啥用

通常来说,js请求数据,无论是异步还是同步,都不会立即获取到结果,通常而言,我们一般是是使用回调函数再执行,而 deferred就是解决jQuery的回调函数方案,总的来说,deferred对象就是为了将某个回调函数延迟到某个时机再执行.

  1. ajax链式写法:

    1. //一般写法:
    2. $.ajax({
    3. url: '',
    4. success: function(){},
    5. error: function(){},
    6. })
    7. //deferred
    8. $.ajax(url)
    9. .done(function(){}) //相当于success
    10. .fail(function(){})
  2. 指定同一操作的多个函数,允许添加多个函数
    写法也很简单,直接添加在后面就可以了。

    1. $.ajax(url)
    2. .done(function(){})
    3. .fail(function(){})
    4. .done(function(){})
  3. 为多个函数添加指定回调,可以为多个不同的函数添加同一个回调事件

    1. $.when($.ajax(url),$.ajax(url2))
    2. .done()
    3. .fail()
    为两个函数执行操作,如果都成功了就执行done中的回调,如果有一个失败或全部都失败,就执行fail中的回调
  4. 普通操作的回调
    deferred允许任何操作都可以使用deferred对象的方法,指定回调函数

    1. var wait = function(de){
    2. var test = function(){
    3. console.log('开始');
    4. de.resolve();
    5. }
    6. setTimeout(test, 3000);
    7. return de;
    8. }
    9. $.when(wait($.Deferred()))
    10. .done(function(){
    11. console.log('已完成')
    12. })
    13. .fail(function(){
    14. console.log('失败')
    15. })

注意: $.when()的参数只能是deferred对象。

咋处理

  1. 关于resolve && rejected
    在上面的时候,会注意到一个resolve,并且会觉得这种链式写法很眼熟,且对promise有一个简单了解的话,大概就知道了。

    1. promise: 同样也是用于处理异步函数,将异步操作队列化处理
    2. 简单的promise
    3. new promise (function(resolve,rejected){
    4. resolve('成功')
    5. })
    6. .then(function(){})
    7. promise.then 接受两个参数:
    8. 一、 resolve 代表成功时调用的函数
    9. 二、 rejected 代表失败时调用的回调
    10. promise的三个状态值: pending(初始状态值), fulfilled(操作成功),rejected(操作失败)
    $.deferred 同样也是有三个不同的状态:未完成,已完成,已失败,当状态处于已完成(resolve)下回自动调用done()中的回调函数,而resolve()就是人为将状态值修改为已完成,同理可证rejected();
    总的来说,核心就是:根据不同的状态值调用回调。
  2. API
    * $.Deferred()
    * $.when()
    * deferred.progress()
    * deferred.promise()
    * deferred.done()
    * deferred.fail()

学习下

来看下jQ的源码是怎么处理的:

  1. Deferred: function(func) {
  2. var tuples = [
  3. // action, add listener, callbacks,
  4. // ... .then handlers, argument index, [final state]
  5. ["notify", "progress", jQuery.Callbacks("memory"),
  6. jQuery.Callbacks("memory"), 2
  7. ],
  8. ["resolve", "done", jQuery.Callbacks("once memory"),
  9. jQuery.Callbacks("once memory"), 0, "resolved"
  10. ],
  11. ["reject", "fail", jQuery.Callbacks("once memory"),
  12. jQuery.Callbacks("once memory"), 1, "rejected"
  13. ]
  14. ],
  15. state = 'pending',
  16. // 延迟对象
  17. deferred = {},
  18. promise = {
  19. state: function() {
  20. return state
  21. },
  22. then: function(){},
  23. promise: function(obj) {
  24. return obj != null ? jQuery.extend(obj, promise): promise;
  25. }
  26. }
  27. ...
  28. }

从代码来看,定一个了数组tuples,以及初始状态值。tuples存储了三个状态下的所需参数,来看下存储了写什么内容:
[状态, 对应的处理函数, 利用callbacks创建的回调队列, then方法的回调队列, index, 最终的状态值],
我们可以看到最终的状态值只有reject 和resolve才有。
ok,已经知道deferred的本质是根据不同的状态调用不同的方法,并且使用callbacks添加函数,那么把tuples遍历一下,生成队列;
源码:

  1. tuples.forEach(function(tuple){
  2. var list = tuple[2], // 获取到jQuery.callbacks返回,创建一个队列
  3. stateString = tuple[5], //获取到最终状态描述
  4. //promise[ progress | done | fail ] = list.add
  5. promise[tuple[1]] = list.add;
  6. // 如果最终状态值存在,即处于 reject|| resolve 状态下;
  7. if (stateString) {
  8. list.add(
  9. function() {
  10. state = stateString;
  11. }
  12. ....
  13. )
  14. }
  15. // 延迟对象状态 deferred.resolve()
  16. //deferred[ 'resolve' | reject | notify] = function(){}
  17. deferred[tuple[0]] = function() {
  18. deferred[tuple[0]+"Width"](this === deferred ? promise : this, arguments);
  19. return this;
  20. }
  21. //jQuery.callbacks.fireWith
  22. //执行队列,调用处理函数,绑定执行时的上下文
  23. deferred[tuple[0] + "With"] = list.fireWith;
  24. })
  25. promise.promise(deferred);
  26. return deferred;

已经遍历生成了3个队列,并将三个状态方法挂载在了延迟对象上。
从代码中可以看出,在调用deferred[ reject | resolve]时,其实是调用了deferred[ rejectWith | resolveWith]方法,本质上是对callbacks.fireWith的调用,以用来执行添加的回调函数,同时设置函数的上下文。
并且可以看的到,deferred[proress | done | fail] 其实是copy了callbacks.add方法,将回调函数添加在了执行队列中。

另外关于对jQuery.deferred对象的详解,使用,https://www.cnblogs.com/chris-oil/p/8922770.html 这篇博文转载了阮大神的,可以瞅瞅

原文链接:http://www.cnblogs.com/xya-b/p/11504665.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号