javascript - 链接 promise (.animate 和 setTimeout 之间的区别)

标签 javascript jquery html promise

我想问一下 javascript 中的 promise 究竟是如何工作的。我很难理解由 jQuery.animate 和 setTimeout 组成的链执行之间的区别。

如果我这样做:

var promise = new Promise(function(resolve, reject) {
    resolve(
        $("#something").animate({
            width: 100
        }, 1000);
    )
});

promise.then(function(data) {
    $("#something").animate({
        height: 100
    }, 1000);
});

然后第二个动画在第一个动画完成后开始(这是想要的行为)。另一方面,当我更改 .then(替换 .animate)时,例如setTimeout 然后在动画开始后立即执行(它不等待动画结束)。

promise.then(function(data) {
    setTimeout(function() {
        console.log("timeout started");
    }, 1000);
});

所以我的问题是:为什么第一种情况可以正常工作而第二种情况不行?我认为异步任务的处理方式相同。以及我应该如何更改代码以正确链接任何函数(等待前面的函数执行)。

最佳答案

首先,jQuery 将通过其内置的动画队列为您在同一对象上序列化动画。您不需要为此使用任何 promise 。

所以,如果你想让你的两个动画一个接一个地出现,你可以简单地这样做而不使用任何 promise :

 $("#something").animate({width: 100}, 1000).animate({height: 100}, 1000);

然后,如果你想在 jQuery 动画中使用 promise,你必须像这样获取动画的 promise:

$("#something").animate({width: 100}, 1000).promise();

然后您可以通过 .then() 使用该 promise 。

如果你想使用 jQuery promises 来控制动画,你可以这样做:

$("#something").animate({width: 100}, 1000).promise().then(function() {
    $("#something").animate({height: 100}, 1000);
});

只是调用:

$("#something").animate({width: 100}, 1000);

在您的原始代码中返回一个 jQuery 对象,它不是 promise 可以单独使用的对象。


如果您真的想创建自己的 promise 对象并自己解决它(jQuery 动画不需要并且在已经有可以使用的 promise 时不推荐这样做),您可以在使用动画中的完成函数来解决你的 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);
});

那么,现在来解释一下您的代码中发生了什么。在您的第一个示例中,您的 promise 逻辑根本不起作用(它几乎只是编码错误)。所以,这两个动画都立即被调用,但是因为 jQuery 将它们排队以便为您顺序运行,这就是您看到的行为。排序与您违背 promise 的逻辑无关。

然后,当您为第二个操作输入 setTimeout() 时,jQuery 不再为您排队,因为它本身不是一个 jQuery 动画,而且您的 promise 逻辑仍然是错误的,所以两者同时执行的操作。


如果你真的只想链接超时,那么你可以制作一个将超时与 promise 结合在一起并且可以链接的包装器:

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 的浏览器)

关于javascript - 链接 promise (.animate 和 setTimeout 之间的区别),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24547215/

相关文章:

javascript - 在 Bootstrap 3 Accordion 中添加动态闭合面板

javascript - 更改数组中特定元素的字体颜色 - Javascript

javascript - 通过数据属性选择带有JS的元素,其中包含引号

javascript - 无法使用 jquery 读取未定义的属性 'clientX'

javascript - 基本初始化故障排除

javascript - 使用 native 输入类型的 jQuery UI 的协议(protocol)相对 URL 方法 ="date"

javascript - 使用 Bootstrap 显示通知计数器

javascript - 如何在文档中获取(具有)最高 CSS z-index 的(元素)?

javascript - 在 ReactJS 中将新的子 DOM 追加到父级中时面临的问题

jquery - JS 在 jsFiddle 中工作正常,但在我的dust.js 模板中却不行