首先,jQuery 将通过其内置的动画队列为您序列化同一对象上的动画。你不需要使用任何 Promise 来做到这一点。
因此,如果您希望两个动画一个接一个,您可以简单地执行此操作,而无需使用任何承诺:
$("#something").animate({width: 100}, 1000).animate({height: 100}, 1000);
然后,如果你想在 jQuery 动画中使用 Promise,你必须像这样获取动画的 Promise:
$("#something").animate({width: 100}, 1000).promise();
然后你可以将这个承诺与.then() 一起使用。
如果你想使用 jQuery Promise 来控制动画,你可以这样做:
$("#something").animate({width: 100}, 1000).promise().then(function() {
$("#something").animate({height: 100}, 1000);
});
只是打电话:
$("#something").animate({width: 100}, 1000);
在您的原始代码中返回一个 jQuery 对象,它不是 Promise 可以单独使用的对象。
如果你真的想创建自己的 Promise 对象并自己解决它(jQuery 动画不需要,并且在已经有可以使用的 Promise 时不推荐使用),你可以在使用动画中的完成函数来解决您的承诺(使用您的编码风格):
var promise = new Promise(function(resolve, reject) {
$("#something").animate({width: 100}, 1000, resolve);
});
promise.then(function(data) {
console.log("timeout started");
setTimeout(function() {
console.log("timeout finished");
}, 1000);
});
所以,现在解释一下您的代码中发生了什么。在您的第一个示例中,您的承诺逻辑根本不起作用(它几乎只是编码错误)。因此,两个动画都被立即调用,但是因为 jQuery 将它们排队以便为您按顺序运行,这就是您看到的行为。排序与您违反承诺的逻辑无关。
然后,当您为第二个操作输入setTimeout() 时,jQuery 不再为您排队,因为它本身不是 jQuery 动画,并且您的承诺逻辑仍然被破坏,因此两个操作同时执行。
如果您真的只想链接超时,那么您可以制作一个将超时与承诺相结合并且可以链接的包装器:
function timer(t) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve();
}, t);
});
}
timer(1000).then(function() {
// do something here
return timer(1000);
}).then(function() {
// do something here
});
工作演示:http://jsfiddle.net/jfriend00/85Pr6/(需要内置 Promise 的浏览器)