我们如何使用jQuery链接应该逐个发生的多个promise?

时间:2016-12-29 12:38:55

标签: jquery promise jquery-deferred deferred

以下是如何在jQuery(1.8及更高版本)中链接多个promise?

foo()
  .then(function() { return bar(); })
  .then(function() { return wah(); })   
  .then(function() { return lah(); })
  .then(function() { return haha(); });

所有foo()bar()wah()lah()haha()都必须返回承诺。

我想一个注意事项是我们必须使用then()而不是done(),因为如果我们使用done(),那么对最后一个操作的第二个操作将在操作后全部启动1完成,而不是一个接一个。

示例:https://jsfiddle.net/jq9d3tw1/

changeStyle($("#message1"), { fontSize: "3em" }, 3000)
  .then(function() { return changeStyle($("#message2"), { marginLeft: "100px" }, 2000) })
  .then(function() { return changeStyle($("#message3"), { opacity: 0 }, 1000) });

其中changeStyle()创建延迟,获取承诺,执行某些操作并在完成时解析承诺,并返回该承诺:

function changeStyle(element, style, duration) {

  var d = new $.Deferred(),
      p = d.promise();

  element.animate(style, duration, function() {
    d.resolve();
  });

  return p;
}

3 个答案:

答案 0 :(得分:2)

通过then回调使用.bind()和动画元素上的.promise()方法,您可以使代码更简洁:



changeStyle($("#message1"), { fontSize: "3em" }, 3000)
  .then(changeStyle.bind($, $("#message2"), { marginLeft: "100px" }, 2000))
  .then(changeStyle.bind($, $("#message3"), { opacity: 0 }, 1000));

function changeStyle(element, style, duration) {
  return element.animate(style, duration).promise();
}

body { font: 24px Arial, sans-serif; }

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="message1">hello</div>
<div id="message2">hi</div>
<div id="message3">ha</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

对于这个特定的用例,jQuery为您提供了使用queue开箱即用的功能。默认情况下,fx队列适用于动画,包括fadeIn()slideUp()等内置动画。

在这种情况下,done函数会在当前元素的动画完成后触发对下一个元素的影响。

var $message1 = $('#message1');
var $message2 = $('#message2');
var $message3 = $('#message3');
$message1.queue(function() {
    $(this).animate(
      { fontSize: "3em" }, 
      {
        duration: 3000, 
        done : function() { $message2.dequeue(); }
      }
    );
});
$message2.queue(function() {
    $(this).animate(
      { marginLeft: "100px" },
      {
        duration: 2000, 
        done : function() { $message3.dequeue(); }
      }
    );
});
$message3.queue(function() {
    $(this).animate({ opacity: 0 }, 1000);
});
$message1.dequeue(); // initiate the first effect

请参阅我的JSFiddle以获取示例

答案 2 :(得分:-2)

如果您要返回承诺,此代码甚至可以更简单 - 您不需要在

中创建一个非常有用的函数
changeStyle($("#message1"), { fontSize: "3em" }, 3000)
  .then(changeStyle($("#message2"), { marginLeft: "100px" }, 2000))
  .then(changeStyle($("#message3"), { opacity: 0 }, 1000));

https://jsfiddle.net/vadimb/jq9d3tw1/1/