JavaScript:.then()传参规则与动画序列执行逻辑疑问
动画序列Promise执行顺序疑问解答
我在完成MDN《动画序列》教程的第二个练习时,写出了可行的代码,但对原理有疑问。代码如下:
const aliceTumbling = [ { transform: 'rotate(0) scale(1)' }, { transform: 'rotate(360deg) scale(0)' } ]; const aliceTiming = { duration: 2000, iterations: 1, fill: 'forwards' } const alice1 = document.querySelector("#alice1"); const alice2 = document.querySelector("#alice2"); const alice3 = document.querySelector("#alice3"); function sinc_animation() { const one = alice1.animate(aliceTumbling, aliceTiming) one.finished.then(() => alice2.animate(aliceTumbling, aliceTiming).finished) .then(() => alice3.animate(aliceTumbling, aliceTiming)) }; sinc_animation();
原本我希望第三个动画在第二个完成后执行,最初在第一个.then()中仅传入alice2.animate(aliceTumbling, aliceTiming),但第三个动画在第二个开始后立即启动,因为此时.then()的Promise被判定为已兑现。现在代码能正常按顺序执行,但有两个疑问:
1. .then()方法中可以传入什么参数?
.then()接受两个可选参数:第一个是Promise兑现(resolved)时触发的回调函数,第二个是Promise拒绝(rejected)时触发的回调函数(通常用.catch()单独处理错误会更清晰)。- 核心是第一个回调函数的返回值:
- 如果返回的是一个Promise对象,后续的
.then()会等待这个新Promise的状态变更(兑现或拒绝)后才会执行。 - 如果返回的是非Promise值(比如普通数据、或者
animate()返回的Animation对象),会被自动包装成一个已兑现的Promise,后续.then()会立刻执行。
- 如果返回的是一个Promise对象,后续的
2. 为什么返回alice2.animate().finished就能让动画按顺序执行?
- 首先,
element.animate()调用后会立刻启动动画,同时返回一个Animation对象;这个对象的finished属性是一个Promise,只有当动画完全结束时,这个Promise才会兑现。 - 你最初的代码里,
.then()回调直接返回alice2.animate(...)的结果(Animation对象,非Promise),所以.then()会马上把它包装成已兑现的Promise,导致第三个动画直接启动,完全不等第二个动画结束。 - 而当你返回
alice2.animate(...).finished时,回调函数返回的是一个Promise。这时Promise链会暂停,直到第二个动画结束(也就是这个finishedPromise兑现),才会执行下一个.then()里的第三个动画。同时,alice2.animate()已经触发了动画执行,所以第二个动画会正常运行,结束后才轮到第三个启动。
内容的提问来源于stack exchange,提问作者Darius
相关产品推荐
相关产品推荐

