jQuery .when().done() 不起作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28575501/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 16:29:13  来源:igfitidea点击:

jQuery .when().done() not working

jquerydeferred

提问by Ronelz

I'd like to start by saying I'm new to jQuery and I suspect I'm just doing something stupid, so hopefully this will be very simple for someone.

我想首先说我是 jQuery 的新手,我怀疑我只是在做一些愚蠢的事情,所以希望这对某人来说非常简单。

I'm trying to add a sliding mobile sub-menu to my website. I want an accordian effect whereby if I click one parent link, it's child sub-menu opens and all other sub-menus close. The problem is timing - the child sub-menu opens and then is closed again by the resetting of all sub-menus. I presume the answer is to use deferreds but everything I've tried has failed. This is the (currently not working) code:

我正在尝试向我的网站添加一个滑动的移动子菜单。我想要一个手风琴效果,如果我点击一个父链接,它的子子菜单打开,所有其他子菜单关闭。问题在于时间——子菜单打开,然后通过重置所有子菜单再次关闭。我认为答案是使用延迟,但我尝试过的一切都失败了。这是(目前不工作)代码:

function ResetMenu(){
    jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
    jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
};

function OpenSubmenu(){
    jQuery(this).next("ul").slideDown(100);
    jQuery(this).parent().addClass("open");
};

jQuery("li.menu-item-has-children > a").click(function(){

    if(jQuery(this).parent().hasClass("open")){
        jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
        jQuery(this).parent().removeClass("open");
    } else {
        jQuery.when(ResetMenu()).done(OpenSubmenu());
    }
    return false;
});

Any help would be greatly appreciated. Thank you!

任何帮助将不胜感激。谢谢!

Ronel

罗内尔

回答by jfriend00

This is a common mistake in how to use jQuery.when().

这是如何使用的常见错误jQuery.when()

jQuery.when()requires promises as arguments. It does not have magical powers to know when functions you pass it are somehow done. Those functions MUST return promises that are resolved or rejected when the underlying code is done and you can then pass those promises to jQuery.when().

jQuery.when()需要 promise 作为参数。它没有神奇的力量知道你传递的函数何时以某种方式完成。这些函数必须返回在底层代码完成时已解决或拒绝的承诺,然后您可以将这些承诺传递给jQuery.when().

Your ResetMenu()function doesn't return anything so therefore, your jQuery.when()doesn't wait for anything. It executes the .then()handler immediately (which looks like that is not what you want).

您的ResetMenu()函数不返回任何内容,因此,您jQuery.when()无需等待任何内容。它.then()立即执行处理程序(这看起来不是您想要的)。

So, in this line:

所以,在这一行:

jQuery.when(ResetMenu()).done(OpenSubmenu());

ResetMenu()MUST return a promise for jQuery.when()to know when it is done.

ResetMenu()必须返回一个承诺jQuery.when()以知道何时完成。

You could fix ResetMenu()to work that way by doing this:

您可以ResetMenu()通过执行以下操作来修复以这种方式工作:

function ResetMenu(){
    return jQuery(".mobile-menu").find(".sub-menu").slideUp(100).promise().then(function() {
        // remove this class when the animation has completed
        jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
    });
};

And, then further, you need to change how you pass a function to .done()to this which both makes it just a function reference that can be executed LATER and binds a appropriate thisvalue to it:

然后,您还需要更改将函数传递.done()给 this 的方式,这既使它只是一个可以稍后执行的函数引用,又为其绑定了一个适当的this值:

jQuery.when(ResetMenu()).done(OpenSubmenu.bind(this));

Note, the .bind(this)assumes that thisis the appropriate value. You can pass whatever value is the correct value there and that will become the thisvalue inside of OpenSubmenu()when it is executed.

请注意,.bind(this)假设this是适当的值。您可以在那里传递任何正确的值,并且thisOpenSubmenu()执行时将成为其中的值。

回答by Arun P Johny

When you pass a non promise object to $.when()the callbacks passed to done()is invoked immediately, in your case when ResetMenuis not returning anything the OpenSubmenuis called immediately, there is another problem also - you should not invoke OpenSubmenudirectly(by adding ()), you need to pass a function reference to done()

当您将非承诺对象$.when()传递给传递给的回调时done()立即调用,在您的情况下,当ResetMenu不返回任何OpenSubmenu立即调用的内容时,还有另一个问题 - 您不应该OpenSubmenu直接调用(通过添加()),您需要传递一个函数参考done()

function ResetMenu() {
    jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
    return jQuery(".mobile-menu").find(".sub-menu").slideUp(100).promise();

};

function OpenSubmenu() {
    jQuery(this).next("ul").slideDown(100);
    jQuery(this).parent().addClass("open");
};

jQuery("li.menu-item-has-children > a").click(function () {

    if (jQuery(this).parent().hasClass("open")) {
        jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
        jQuery(this).parent().removeClass("open");
    } else {
        jQuery.when(ResetMenu()).done(OpenSubmenu);
    }
    return false;
});