async事件监听器中setTimeout与自定义delay函数均不执行如何解决?
问题根本原因
你的猜测完全正确,问题由switchToSearch()函数触发:
- 执行
window.location.href = "./movies"会立即触发当前页面跳转,浏览器会直接销毁当前页面的所有JS执行上下文,所有未执行的异步回调(包括你注册的setTimeout回调、未完成的Promise回调)都会被直接清除,永远不会执行。 - 额外补充:你自定义的
delay函数本身也存在逻辑错误,Promise构造器中没有调用resolve(),所以即使没有页面跳转,await delay(5000)也会永远处于pending状态,不会执行后续代码。
解决方法
根据你的业务场景二选一即可:
场景1:需要在当前页面跳转前执行populateForm
把页面跳转逻辑放到setTimeout内部,等所有逻辑执行完再跳转:
async function addClickListener() { const items = document.querySelectorAll(".li"); items.forEach((item) => { item.addEventListener("click", async (evt) => { evt.preventDefault(); sessionStorage.clear(); const movieData = await createMovieObject(evt.currentTarget); sessionStorage.setItem("movieData", JSON.stringify(movieData)); clearMovieList(); removeHidden(); // 把跳转放到setTimeout内部最后执行 setTimeout(function () { console.log("hello"); populateForm(); switchToSearch(); }, 5000); }); }); }
如果要用await delay的写法,先修正delay函数:
// 修正后的delay函数 const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)) // 调用逻辑 await delay(5000) console.log("hello"); populateForm(); switchToSearch();
场景2:populateForm是跳转后./movies页面的逻辑
直接把执行逻辑迁移到新页面的JS代码中即可,同域名下sessionStorage的内容不会因为页面跳转丢失:
// 写在./movies页面对应的JS中 document.addEventListener('DOMContentLoaded', () => { // 存在movieData时执行对应逻辑 if (sessionStorage.getItem('movieData')) { populateForm() // 可选:执行完成后清除存储,避免重复触发 // sessionStorage.removeItem('movieData') } })
内容的提问来源于stack exchange,提问作者Saoma
相关产品推荐
相关产品推荐

