2013-12-19 72 views
1

我的代码:如何顺序调用延期功能?

<?php 
if(isset($_GET['m'])) { 
    $m = $_GET['m']; 
    sleep($m); 
    print "done, m=$m"; 
    die; 
} 
?> 

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script> 
<script> 

    function w(s) { 
     document.body.innerHTML = document.body.innerHTML+ "<br>" + s 
    } 

    function aaa(def) { 
     w("begin aaa"); 
     $.ajax({ 
      type: "GET", 
      data: { 
       m: 5 
      } 
     }).done(function(html) { 
      w(html); 
      def.resolve(); 
     }); 
    } 


    function bbb(def) { 
     w("begin bbb"); 
     $.ajax({ 
      type: "GET", 
      data: { 
       m: 1 
      } 
     }).done(function(html) { 
      w(html); 
      def.resolve(); 
     }); 
    } 

    $(function() { 

     $.when(
      $.Deferred(function(d) { aaa(d) }).promise(), 
      $.Deferred(function(d) { bbb(d) }).promise() 
     ).done(function() { 
      w("OK") 
     }); 
    }) 
</script> 

我期待第二个函数等待第一个完成的,也就是我的输出应该是

begin aaa 
    <--pause 
done, m=1 
begin bbb 
    <--pause 
done, m=5 
OK 

相反,我得到

begin aaa 
begin bbb 
    <--pause 
done, m=1 
    <--pause 
done, m=5 
OK 

我想我误解了关于延迟如何工作的一些基本问题 - 任何人都可以点亮?

回答

7

如果它们之间没有依赖关系,你会如何按顺序执行它们? $.when对承诺的评估没有影响,它只是等待,直到每个承诺得到解决。

你的代码要复杂得多。 $.ajax已经返回一个承诺,当接收到Ajax响应时会得到解决,所以您可以从函数中返回。如果您希望按顺序执行它们,你可以通过.then把它们连:

这些过滤函数可以返回一起承诺的.done().fail()回调传递一个新的价值,或者他们可以返回另一个观察的对象(延期,承诺等),将其解决/拒绝的状态和价值传递给承诺的回调。

所以,你的代码可以简化为:

function aaa() { 
    w("begin aaa"); 
    return $.ajax({ 
     type: "GET", 
     data: { 
      m: 5 
     } 
    }).done(w); 
} 


function bbb() { 
    w("begin bbb"); 
    return $.ajax({ 
     type: "GET", 
     data: { 
      m: 1 
     } 
    }).done(w); 
} 

aaa().then(bbb).done(function() { w('ok'); }); 

在这里,aaa().then(bbb)创建你需要的依赖。它基本上意味着“一旦aaa的承诺解决了,执行bbb”。另外,.then返回一个新的承诺,当bbb返回的承诺得到解决时,该承诺得到解决,这允许您在解决了承诺aaabbb的情况下执行函数。

也许这些帮助您了解的承诺(和deferreds)更好:


例无$.ajax

function aaa() { 
    var def = new $.Deferred(); 
    setTimeout(function() { 
     def.resolve(21); 
    }, 3000); 
    return def.promise(); 
} 

function bbb(v) { 
    var def = new $.Deferred(); 
    setTimeout(function() { 
     def.resolve(v * 2); 
    }, 1000); 
    return def.promise(); 
} 

// aaa -> bbb -> console.log 
// The value is logged after 3 + 1 seconds 
aaa().then(bbb).done(function(v) { console.log(v); }); // 42 

// (aaa | bbb) -> console.log 
// The value is logged after max(3, 1) seconds and both resolved values are 
// passed to the final promise 
$.when(aaa(), bbb(5)).done(function(v) { console.log(v); }); // [21, 10] 
+0

完美,谢谢! – georg

+0

所以,如果你想连锁,'A - > B - > C',使用'.then'。如果你想并行运行它们并在完成时做一些事情,'(A | B) - > C',使用'$ .when' :)并且你的欢迎! –

+0

为了让我更好地理解,你可以添加一个例子,而不是''.ajax',而不是延迟本身,例如, 'setTimeout'。 – georg

1

$.when()没有对其论点施加任何顺序 - 它们实际上是“无序列表”。

然而,.done(),.fail().then()确实施加了命令。

首先,通过修改aaa()bbb()返回由$.ajax().done()链返回无极兼容的对象事情简单化,具体如下:

function aaa() { 
    w("begin aaa"); 
    return $.ajax({ 
     type: "GET", 
     data: { m: 5 } 
    }).done(w);//without changing anything, w can be passed rather than called from an anonymous function. 
} 

function bbb() { 
    w("begin bbb"); 
    return $.ajax({ 
     type: "GET", 
     data: { m: 1 } 
    }).done(w);//without changing anything, w can be passed rather than called from an anonymous function. 
} 

现在,让你追求的效果,使用.then()测序aaabbb

$(function() { 
    aaa().then(bbb).done(function() { 
     w("OK"); 
    }); 
}); 

我同意它稍微混乱这里是aaa执行和bbb已通过,但这是一个很常见的模式,你会一次又一次遇到。最终它会有道理。

为了把aaabbb看齐对方,你可以写这样的:

$(function() { 
    $.Deferred().resolve().then(aaa).then(bbb).done(function() { 
     w("OK"); 
    }); 
}); 
+0

谢谢,非常有帮助。我希望你和菲利克斯的答案使这是一个很好的参考主题。 – georg