简体   繁体   English

链接Promises(.animate和setTimeout之间的差异)

[英]chaining Promises (difference between .animate and setTimeout)

I want to ask how exactly promises in javascript work. 我想问一下javascript中的承诺是如何运作的。 I am having hard time to understand difference between execution of chain composed of jQuery.animate and setTimeout. 我很难理解由jQuery.animate和setTimeout组成的链的执行之间的区别。

If I do something like this: 如果我做这样的事情:

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

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

Then the second animation starts after the first one is completed (which is wanted behavior). 然后第二个动画在第一个动画完成后开始(这是想要的行为)。 On the other hand, when I change .then (replace .animate ) with eg setTimeout then it is executed right after the animation is started (it does not wait for animation to end). 在另一方面,当我改变.then (更换.animate )与如setTimeout话,那就是动画开始后立即执行(不等待动画结束)。

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

So my question is: why the first scenario works fine and the second does not? 所以我的问题是:为什么第一种情况正常,第二种情况不正常? I thought that asynchronous tasks are handled in the same way. 我认为异步任务以相同的方式处理。 And how should I change the code to properly chain any functions (to wait for the previous ones to execute). 我应该如何更改代码以正确链接任何函数(等待先前的函数执行)。

First off, jQuery will serialize animations on the same object for you via it's built-in animation queue. 首先,jQuery将通过它的内置动画队列为您在同一对象上序列化动画。 You don't need to use any promises in order to do that. 你不需要使用任何承诺来做到这一点。

So, if you want your two animations to be one after the other, you can simply do this without any use of promises: 所以,如果你想让你的两个动画一个接一个,你可以简单地做到这一点而不使用任何承诺:

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

Then, if you want to use promises with jQuery animations, you have to obtain the promise for the animation like this: 然后,如果你想使用jQuery动画的promises,你必须获得动画的承诺,如下所示:

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

and then you can use that promise with .then() . 然后你可以使用.then()那个承诺。

If you wanted to use jQuery promises to control the animations, you could do this: 如果你想使用jQuery promises来控制动画,你可以这样做:

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

Just calling: 只是打电话:

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

in your original code returns a jQuery object which is not something a promise can use by itself. 在您的原始代码中返回一个jQuery对象,这不是一个promise本身可以使用的东西。


If you really wanted to create your own promise object and resolve it yourself (something that is not required with jQuery animations and not recommended when there's already a promise that you can use), you could so do like this where you use the completion function from the animation to resolve your promise (using your coding style): 如果你真的想创建自己的promise对象并自己解决它(jQuery动画不需要的东西,当你已经有一个可以使用的承诺时不推荐),你可以这样做,你可以使用完成函数动画来解决你的承诺(使用你的编码风格):

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);
});

So, now to explain what was going on in your code. 所以,现在来解释你的代码中发生了什么。 In your first example, your promise logic wasn't working at all (it was pretty much just coded wrong). 在您的第一个示例中,您的承诺逻辑根本不起作用(它几乎只是编码错误)。 So, both animations were getting called immediately, but because jQuery queues them to run sequentially for you, that's the behavior you saw. 因此,两个动画都会被立即调用,但是因为jQuery将它们排队为你顺序运行,这就是你看到的行为。 The sequencing had nothing to do with your broken promise logic. 排序与破坏的承诺逻辑无关。

Then, when you put in the setTimeout() for the second operation, jQuery was no longer queuing that for you because it's not a jQuery animation by itself and your promise logic was still broken so both operations executed at the same time. 然后,当您为第二个操作输入setTimeout() ,jQuery不再为您排队,因为它本身不是jQuery动画,并且您的promise逻辑仍然被破坏,因此两个操作同时执行。


If you really want to just chain timeouts, then you can make a wrapper that combines a timeout with a promise and that can be chainable: 如果你真的想要链接超时,那么你可以创建一个包含超时和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
});

Working demo: http://jsfiddle.net/jfriend00/85Pr6/ (requires browser that has promises built-in) 工作演示: http//jsfiddle.net/jfriend00/85Pr6/ (需要内置承诺的浏览器)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM