javascript - 如何减少 javascript/jquery 中的嵌套回调

标签 javascript jquery

我的任务是重写这段可怕的代码,该代码旨在按顺序淡入网页上 map 上的图层(它们都是透明的 png)。它需要按顺序运行,然后循环回到没有层可见的起点,然后一次淡入一个层。这个序列应该永远重复。

我不太确定在 javascript 中最推荐的执行此操作的方法是什么,并且对堆栈溢出必须说的内容很感兴趣。

必须有比这更好的方法!我对任何方法的优缺点感兴趣。

setInterval(function(){
    $("#layer-1").fadeIn(1000, function() {
      $("#layer-2").fadeIn(1000, function() {
        $("#layer-3").fadeIn(1000, function() {
          $("#layer-4").fadeIn(1000, function() {
            $("#layer-5").fadeIn(1000, function() {
              $("#layer-6").fadeIn(1000, function() {
                $("#layer-7").fadeIn(1000, function() {
                  $("#layer-8").fadeIn(1000, function() {
                    // pause for 2 seconds, then reset and hide all layers:
                    $("#home-map .layer").delay(2000).fadeOut();
                  });
                });
              });
            });
          });
        });
      });
    });
  }, 10000)

编辑:我认为这与其他答案不同的原因是因为我试图将事情设置为无限循环,以及链接动画。 javascript 中有很多解决回调 hell 的方法,这是一个很常见的症结所在,所以毫无疑问会有类似的问题。

最佳答案

通过使用异步等待 + promise

如果您在动画后调用 .promise(),您将得到一个 promise 。感谢它,您可以等待它完成

async function animate() {
    await $("#layer-1").fadeIn(1000).promise()
    await $("#layer-2").fadeIn(1000).promise()
    await $("#layer-3").fadeIn(1000).promise()
    await $("#layer-4").fadeIn(1000).promise()
    await $("#layer-5").fadeIn(1000).promise()
    await $("#layer-6").fadeIn(1000).promise()
    await $("#layer-7").fadeIn(1000).promise()
    await $("#layer-8").fadeIn(1000).promise()
    // pause for 2 seconds, then reset and hide all layers:
    await $("#home-map .layer").delay(2000).fadeOut().promise();
}

const loop = () => animate().then(loop)
loop()

看看这个,for 循环非常适合。

async function animate() {
    for (let i = 1; i < 9; i++)
        await $(`#layer-${i}`).fadeIn(1000).promise()

    // pause for 2 seconds, then reset and hide all layers:
    await $("#home-map .layer").delay(2000).fadeOut();
}

这只有在最新的浏览器中才有可能


如果你这样做的话,我猜它可以变得更有活力

for (let layer of $("#home-map .layer"))
    await $(layer).fadeIn(1000).promise()

这是相同问题的 es5 替代方案,但使用 reduce to chain promises

function animate() {
  $(".layer").toArray().reduce(function(prev, elm){
    return prev.then(function(){
      return $(elm).fadeIn(1000).promise();
    })
  }, Promise.resolve()).then(function(){
    // do the master
    $(".masterLayer").delay(2000).fadeOut();
  })
}

animate()
.layer {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="masterLayer">
  <div class="layer">layer 1</div>
  <div class="layer">layer 2</div>
  <div class="layer">layer 3</div>
  <div class="layer">layer 4</div>
  <div class="layer">layer 5</div>
  <div class="layer">layer 6</div>
</div>

关于javascript - 如何减少 javascript/jquery 中的嵌套回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43664279/

相关文章:

javascript - jquery 代码工作正常,但其他单选按钮干扰其工作

javascript - 在 Angular Material Accordion 中打开第一个附加的扩展面板

php - 在 php 中设置 javascaript 变量(php 在 javascript 中)

javascript - Firebase数据库返回null;刷新后,它返回正确的值

javascript - 在缩放/拖动时缩放/重绘 d3.js 网格线

php - 具有两个按钮的表单以不同的值提交

javascript - 如果整个元素都在 View 中,则元素位置为 :fixed?

javascript - jQuery 日期选择器在页面加载时隐藏时不会初始化

javascript - $ 不是 jQuery .hover() 方法的函数吗?

c# - “WMD”Web Markdown 以及如何实现图像上传功能