2015-05-30 44 views
1

能anyoune请澄清什么是错用下面的代码(也读了不少文档和例子,但仍然有不知道发生了什么事)意外的延迟对象的行为

function t() { 
    var d = $.Deferred(); 
    setTimeout(function(){ 
     d.resolve(); 
    }, 5000); 
    return d.promise(); 
} 
function test() { 
    var dd = $.Deferred(); 
    $.ajax("/echo/json/").done(function() { 
     dd = t(); 
     dd.done(function() { alert(" dd.done inside ajax")}); 
    }); 
    dd.done(function() { alert(" dd.done outside ajax")}); 
} 
test(); 

产量为(以〜5 s):

"dd.done inside ajax:" 

为什么第二个.done不起作用?

+0

你盛开了开发者控制台,以检查是否存在错误? – Pointy

+0

没有错误,但奇怪的是,第一个console.log(替换alert和url在浏览器中运行)输出已经翻了一番。 W.T.H.? –

回答

0

您的第二个警报永远不会被调用,因为您原来的延迟分配给变量dd永远不会被调用,因此它的.done()处理程序永远不会被调用。

您创建一个延迟,并将其分配给dd这里:

var dd = $.Deferred(); 

而且,当时您设置.done()处理这个:

dd.done(function() { alert(" dd.done outside ajax")}); 

但是,当你的Ajax功能完成后,您分配一个不同的承诺,用这一行dd变量:

dd = t(); 

因此,没有任何东西能够解决原来的承诺,所以它的.done()处理程序永远不会被调用。


我建议这样的设计来代替:

function t() { 
    var d = $.Deferred(); 
    setTimeout(function(){ 
     d.resolve(); 
    }, 5000); 
    return d.promise(); 
} 
function test() { 
    return $.ajax("/echo/json/").then(function() { 
     console.log("ajax call done"); 
     return t(); 
    }).then(function() { 
     console.log("after timer"); 
    }); 
} 

test().then(function() { 
    console.log("everything done"); 
}); 

工作演示:http://jsfiddle.net/jfriend00/atafc5hj/

这说明了以下概念这些都是了解的:

  1. 使用承诺已从$.ajax()返回,而不是创建自己的。
  2. 链接另一个承诺的活动。
  3. .then()处理程序返回另一个承诺,以使序列也等待该承诺。
  4. 从主函数返回链接的承诺,以便您可以看到什么时候完成所有事情。

+0

太好了,现在我清楚地看到了一些事情,特别感谢建议的解决方案,这有助于理解一个主题,并且避免了我周末的头痛 –

+0

但是...)仍然有一件事对我来说似乎不清楚。我注意到你使用.then()来分配回调而不是.done()。 我运行你的代码(完美工作,再次感谢),除了使用.done而不是.dhen这里︰drrrrrrrrrrrrrrrrrrrrrrrrrr: **返回$ .ajax(“/ echo/json /”)导致立即执行第二次回调(“定时器之后”),就好像它被分配给已经解析的延迟对象一样。 –

+0

我使用.then(),因为它是promise的标准处事方式,而不是jQuery的发明 – jfriend00

1

因为该延迟对象未解析。您正在创建2个延迟对象并解析其中的一个。

2

让我们来看看test()

function test() { 
    var dd = $.Deferred(); 
    $.ajax("/echo/json/").done(function() { 
     dd = t(); 
     dd.done(function() { alert(" dd.done inside ajax")}); 
    }); 
    dd.done(function() { alert(" dd.done outside ajax")}); 
} 
test(); 

局部变量dd被初始化到一个新的jQuery Deferred对象。然后,开始ajax操作,并给出一个“完成”回调,它将调用其他测试功能t()

$.ajax()调用将在其.done()回调运行很久之前立即返回。在此之后,为函数开头创建的Deferred实例建立另一个.done()回调。

现在,当阿贾克斯“完成”回调运行的dd —最初创建的Deferred对象—值将是覆盖与无极从t()返回。最终.done()回调将会运行,但是没有任何东西可以解决第一个Deferred实例,所以“外部”回调不会发生。

+0

谢谢。我看到我的错在哪里 –