zoukankan      html  css  js  c++  java
  • Deferred对象

    摘要:虽然js已经出了ES6,ES7等等版本,从而也诞生了新的异步对象->promise,但是基础还是要终结的,这一片就来回顾一下ajax以及ajax的异步对象->deferred。

    1.传统ajax

    传统模式$.ajax()接受参数为一个对象,该对象包含了callback(success和error)

    栗子:

     1 function toJson(data) {
     2     document.write('<pre><code>' + JSON.stringify(data) + '</code></pre>');
     3 }
     4 $.ajax({
     5     url: "http://yapi.demo.qunar.com/mock/10343/getinfo",
     6     success: function (data) {
     7         toJson(data);
     8     },
     9     error: function (error) {
    10         console.log('error');
    11     }
    12 });

    这里安利一个第三方平台YAPI,可以通过YAPI模拟server端。

    运行结果:

    2.随着jQuery的改进,新的写法诞生了

    栗子:

     1 function toJson(data) {
     2     document.write('<pre><code>' + JSON.stringify(data) + '</code></pre>');
     3 }
     4 $.ajax("http://yapi.demo.qunar.com/mock/10343/getinfo")
     5 .done(function(data){
     6     toJson(data);
     7 })
     8 .fail(function(e){
     9     console.log(e);
    10 })

    运行结果:

    增加了链式用法。这是为啥呢。因为jQuery在1.5.0版本以后增加了deferred对象,支持了链式调用方式。

    3.增加了多个延迟函数公用一个回调函数,于是$.when()诞生了。

    栗子:

     1 function toJson(arr) {
     2     arr.forEach(a => {
     3         document.write('<pre><code>' + JSON.stringify(a) + '</code></pre>');
     4     })
     5 }
     6 $.when($.ajax("http://yapi.demo.qunar.com/mock/10343/getinfo"),
     7     $.ajax("http://yapi.demo.qunar.com/mock/10343/getinfo"))
     8     .done(function (data, data2) {
     9         toJson([data[0], data2[0]]);
    10     })
    11     .fail(function (e) {
    12         console.log(e);
    13     })

    结果:

    这里如果两个ajax如果其中有一个失败则会调用fail的callback,到这里如果异步不是ajax呢,是setTimeout呢~

    栗子:

    1 function wait() {
    2     var delayFn = function () {
    3         console.log('over.');
    4     };
    5     setTimeout(delayFn, 5000);
    6 };

    要知道执行函数wait的时候,delayFn会以一个新的宏任务从新扔到一个事件队列里,这时两个函数变成为了异步,那么这时候出现一个新的函数,如何控制新的函数要执行与延迟函数之后呢。

    方式1:讲函数写在延迟函数内,这不废话吗。

    方式2:如果与wait在同属一个宏任务呢?答案是利用$.when(),以微任务的形式存在。这样等延迟函数执行完再去执行,就是我们上面栗子3的形式了。

    栗子:

     1 function wait(dtd) {
     2     console.log(new Date())
     3     var delayFn = function () {
     4     };
     5     setTimeout(delayFn, 5000);
     6 };
     7 $.when(wait())
     8     .done(function (data) {
     9         console.log(new Date());
    10     })
    11     .fail(function (e) {
    12         console.log(e)
    13     })

    执行结果:

    事实上并没有等延迟函数执行完,才进入的回调函数,似乎直接就执行了回调函数,这是为啥呢?

    原因是:$.when()接受的对象必须是deferred对象,否则会立即执行回调函数。改进如下。

    栗子:

     1 var dtd = $.Deferred();
     2 function wait(dtd) {
     3     console.log(new Date())
     4     var delayFn = function () {
     5         dtd.resolve();
     6     };
     7     setTimeout(delayFn, 5000);
     8     return dtd;
     9 };
    10 $.when(wait(dtd))
    11     .done(function (data) {
    12         console.log(new Date());
    13     })
    14     .fail(function (e) {
    15         console.log(e)
    16     })

    运行结果:

    deferred对象此外还有两个方法分别是:reject()、promise()

    resolve:改变deferred对象的状态,执行done callback。

    reject:reject()与reslove()方法一样,同为改变deferred对象的状态,当状态为reject时,这执行fail callback。

    promise:重新生成deferred对象。

    4.promise对象

    我猜ES6也是根据这个词儿诞生的promise对象,嘿嘿。

    上面栗子可以看到dtd是外部传入的对象,在wait以外就可以改变deferred对象状态,直接执行回调函数

    栗子:

     1 function toJson(arr) {
     2     arr.forEach(a => {
     3         document.write('<pre><code>' + JSON.stringify(a) + '</code></pre>');
     4     })
     5 }
     6 var dtd = $.Deferred();
     7 function wait(dtd) {
     8     console.log(new Date())
     9     var delayFn = function () {
    10         dtd.resolve();
    11     };
    12     setTimeout(delayFn, 5000);
    13     return dtd;
    14 };
    15 $.when(wait(dtd))
    16     .done(function (data) {
    17         console.log(new Date());
    18     })
    19     .fail(function (e) {
    20         console.log('error' + ' time:' + new Date())
    21     })
    22 dtd.reject();

    执行结果:

    可以看到在外面修改deferred状态就会立即执行fail callback函数了。那么如何避免呢~,我们利用promise() 重新生成一个deferred对象。

     栗子:

     1 function toJson(arr) {
     2     arr.forEach(a => {
     3         document.write('<pre><code>' + JSON.stringify(a) + '</code></pre>');
     4     })
     5 }
     6 var dtd = $.Deferred();
     7 var waitDtd = function wait(dtd) {
     8     console.log(new Date())
     9     var delayFn = function () {
    10         dtd.resolve();
    11     };
    12     setTimeout(delayFn, 5000);
    13     return dtd.promise();
    14 };
    15 $.when(waitDtd)
    16     .done(function (data) {
    17         console.log(new Date());
    18     })
    19     .fail(function (e) {
    20         console.log('error' + ' time:' + new Date())
    21     })
    22 waitDtd.reject();

    over~

  • 相关阅读:
    BizTalk 2010 Adapter for mySAP Business Suite 所支持版本
    BizTalk Adapter Pack for Oracle 实现Oracle 11g的CRUD
    BizTalk 360 功能介绍 CTP版
    以小见大——那些基于 protobuf 的五花八门的 RPC(5 完)
    BizTalk Server 2010 + SQL Server 2008 R2 通过集成创造更大价值 [ 上篇 ]
    double to float
    Office 2003 PIA
    matlab传参数
    Convert.ToInt16
    矩阵转换
  • 原文地址:https://www.cnblogs.com/moran1992/p/10418960.html
Copyright © 2011-2022 走看看