【问题标题】:How to wait for a jQuery toggle to finish before running another function?如何在运行另一个函数之前等待 jQuery 切换完成?
【发布时间】:2018-10-29 23:26:58
【问题描述】:

我遗漏了一些非常明显的东西,但我不能让我的一种方法等到 jQuery 切换完成。

我有以下三种方法:

const toggleContainer = function() {
  addAnswerContainer.toggle("slow");
};

const toggleButtons = function() {
  submitAnswerBtn.toggle("slow");
  cancelAnswerBtn.toggle("slow");
};

const changeText = function() {
  if( addAnswerContainer.is(":hidden") ) {
    addOwnAnswerBtn.text("Add your own answer" );
  }
  else {
    addOwnAnswerBtn.text("Hide adding answer");
  }
};

我想做的就是让这样的事情起作用:

const toggleUI = function() {
  toggleContainer();
  toggleButtons();
  changeText(); // executes too fast
};

问题是changeText() 执行太快,每次检查时,addAnswerContainer.is(":hidden") 都会返回false,除非我setTimeout 它几秒钟,这不是我想要的。我尝试了回调,也尝试了 Promises,但我就是无法让它工作。我怎样才能让changeText() 等待,直到addAnswerContainer.toggle() 完成它的工作?

【问题讨论】:

  • 您在使用回调方法时遇到了哪些错误?
  • @AndrewL 使用回调方法我没有任何错误,但它又太快了。但那是因为我自己做了回调,我才意识到 jQuery 切换也接受了回调

标签: javascript jquery callback promise method-chaining


【解决方案1】:

可以从切换函数返回$.whenpromise,并使用promise()中要解析的元素对象$.when。

在承诺链的下一个then() 中调用下一步

简化演示

const toggleComplete = function(){
   console.log('finished animation id #', this.id)
}

const toggleButtons = function (){
  // toggleComplete only needed for this demo
  let p1=$('#1').toggle('slow',toggleComplete).promise()
  let p2=$('#2').toggle('slow',toggleComplete).promise()
 
  return $.when(p1,p2)
}

toggleButtons().then(_=>console.log('all animations done')/* change text here*/)
div{display:none}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="1">
One
</div>

<div id="2">
Two
</div>

【讨论】:

    【解决方案2】:

    我可能会在您的 if-else 语句之后建议一种简单但聪明的方法,如下所示:

    const toggleContainer = function() {
      addAnswerContainer.toggle("slow");
      return true;
    };
    
    const toggleButtons = function() {
      submitAnswerBtn.toggle("slow");
      cancelAnswerBtn.toggle("slow");
    };
    
    const ToggleIfTrue = () => {
      if(addAnswerContainer.is(":hidden") && toggleContainer) { 
        addOwnAnswerBtn.text("Add your own answer" );
      }
      else if (addAnswerContainer.is(!":hidden") && toggleContainer) {
        addOwnAnswerBtn.text("Hide adding answer");
      }
    };
    

    这样,内部 if-else 语句仅在 addAnswerContainer 设置为 hidden 时运行,反之则与最后的 else if 语句相反

    【讨论】:

    • 我在使用这个解决方案时遇到了同样的问题。 addAnswerContainer 现在总是隐藏
    【解决方案3】:

    .toggle( [duration ] [, complete ] )

    可选的第二个参数是动画完成后要调用的函数,因此只需使用所需的回调调用toggle。 Promise 是执行此类操作的最佳方式:

    const toggleContainer = () => new Promise(resolve =>
      addAnswerContainer.toggle("slow", resolve)
    );
    
    const toggleButtons = () => new Promise(resolve => {
        submitAnswerBtn.toggle("slow");
        cancelAnswerBtn.toggle("slow", resolve);
    });
    
    const changeText = function() {
      if( addAnswerContainer.is(":hidden") ) {
        addOwnAnswerBtn.text("Add your own answer" );
      }
      else {
        addOwnAnswerBtn.text("Hide adding answer");
      }
    };
    

    然后在 Promise 上调用 .then 以链接异步函数:

    const toggleUI = function() {
      toggleContainer()
        .then(toggleButtons)
        .then(changeText);
    };
    

    或者如果你想让toggleContainer和toggleButtons同时运行,并且只在changeText之前等待:

    const toggleUI = function() {
      toggleContainer()
      toggleButtons()
        .then(changeText);
    };
    

    【讨论】:

    • 是的,太棒了,这已经解决了问题。它的工作原理非常有趣,我现在正在尝试理解它。
    • 另外,当我看到你的评论时,我意识到 jQuery 切换本身有一个回调,我设法使它与它一起工作:const toggleUI = function() { addAnswerContainer.toggle("slow", function() { submitAnswerBtn.toggle("slow"); cancelAnswerBtn.toggle("slow", function() { changeText(); }); }); }; 但你的解决方案正是我首先想要的。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多