You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

原生JS(无jQuery)结合Promise/async/await实现淡入淡出替换元素问题排查

原生JS淡入淡出切换动画失效问题修复

核心错误点

代码一共存在3个直接导致效果异常的问题:

  • Promise未正确决议,异步流程卡断:fadeOut函数内部全程没有调用resolve(),当1秒淡出动画执行完成后,返回的Promise永远处于pending状态,await会一直卡在这一行,后续的fadeIn逻辑根本不会被执行,新元素自然一直保持初始透明状态无法显示。
  • fadeIn的resolve时机错误:fadeIn里把resolve(elem)写在了setInterval启动逻辑的外部,动画刚初始化就直接返回,根本不会等待淡入动画执行完成,无法保证时序控制。
  • 空元素分支未处理Promise状态:两个动画函数里判断!elem直接return的分支,都没有决议Promise,一旦传入不存在的元素会直接导致整个异步流程永久挂起。

修正后的完整代码

HTML代码

<div id="main">
  <div class="x">
    blah
  </div>
</div>

CSS代码

.asd1 {
  width: 100px;
  height: 100px;
  background-color: red;
  opacity: 0;
}

.x {
  width: 50px;
  height: 50px;
  background-color: purple;
}

JavaScript代码

const main = document.querySelector('#main');
const el0 = document.querySelector('.x');
const str = '<div class="asd1">Hello</div>'; // generated from fetch result
main.insertAdjacentHTML('beforeend', str);
const el1 = document.querySelector('.asd1');

(async() => {
  await fadeOut(el0, 1000);
  await fadeIn(el1, 1000);
})();

function fadeIn(elem, ms) {
  return new Promise((resolve) => {
    if (!elem) {
      resolve();
      return;
    }

    elem.style.opacity = 0;
    elem.style.filter = "alpha(opacity=0)";
    elem.style.display = "inline-block";
    elem.style.visibility = "visible";

    if (ms) {
      let opacity = 0;
      const timer = setInterval(function() {
        opacity += 50 / ms;
        if (opacity >= 1) {
          clearInterval(timer);
          opacity = 1;
          resolve(elem);
        }
        elem.style.opacity = opacity;
        elem.style.filter = "alpha(opacity=" + opacity * 100 + ")";
      }, 50);
    } else {
      elem.style.opacity = 1;
      elem.style.filter = "alpha(opacity=1)";
      resolve(elem);
    }
  });
}

function fadeOut(elem, ms) {
  return new Promise((resolve) => {
    if (!elem) {
      resolve();
      return;
    }

    if (ms) {
      let opacity = 1;
      const timer = setInterval(function() {
        opacity -= 50 / ms;
        if (opacity <= 0) {
          clearInterval(timer);
          opacity = 0;
          elem.style.display = "none";
          elem.style.visibility = "hidden";
          resolve(elem);
        }
        elem.style.opacity = opacity;
        elem.style.filter = "alpha(opacity=" + opacity * 100 + ")";
      }, 50);
    } else {
      elem.style.opacity = 0;
      elem.style.filter = "alpha(opacity=0)";
      elem.style.display = "none";
      elem.style.visibility = "hidden";
      resolve(elem);
    }
  });
}

补充说明:如果不需要兼容IE8及更早版本,完全不需要手动写setInterval实现动画,用原生CSS transition搭配transitionend事件监听实现动画,代码更简洁、性能更好。

内容的提问来源于stack exchange,提问作者dapidmini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 13:24:21