点击处理程序内的Promise.resolve()

问题描述 投票:1回答:1

我正在尝试为某些事件处理程序创建一些装饰器:一些以处理程序A作为参数并返回函数B的简单函数,该函数执行一些操作,然后调用 A(...arguments)

我特别想构建一个装饰器,它应该在所有其他处理程序之后触发作为参数传递的处理程序。但是我注意到,如果事件是通过编程方式而不是手动方式触发的,则点击处理是不同的。

<a href="some/path">bla</a>标记的情况下特别明显,在[click]事件上带有异步处理程序,该处理程序等待下一个线程完成其执行(即,在某个时刻具有< [await Promise.resolve())。例如,给出此代码

<a href="">click</a> <script> const a = document.querySelector('a') a.addEventListener('click', fireLastDecorator(handler)) a.addEventListener('click', () => console.log('doing stuff...')) setTimeout(click, 10000) function handler(e) { e.preventDefault() console.log('done') } function fireLastDecorator(f) { return async function() { await Promise.resolve() f.apply(this, arguments) } } function click() { a.click() } </script>

在10秒钟的超时期间,我可以随时在链接上单击任意按钮:该页面不会重新加载,因为即使存在

[e.preventDefault()

await Promise.resolve()语句也会阻止链接的加载。但是当setTimeout触发其click函数(以编程方式)时,一旦程序等待

await Promise.resolve()

,页面就会开始重新加载自身。该函数在等待之后继续执行(如果您激活了持久日志,则可以在控制台上看到'done'字符串打印),但是无论如何页面都将重新加载。
我不知道为什么这种行为与众不同。

这在输入类型提交时也很明显。

编辑

使用调试器,我注意到当手动而不是通过js触发单击时,脚本会遵循不同的路径:手动触发时,处理程序不会等待Promise解析,因此第二个处理程序在首先(就像Promise.resolve()被忽略)。通过js触发时,该处理程序会等待诺言,因此添加的第二个处理程序会在第一个处理程序之前触发。

我正在尝试为某些事件处理程序制作一些装饰器:一些简单的函数,这些函数以处理程序A作为参数,并返回执行某些操作然后调用A(... arguments)的函数B。那里...

javascript dom
1个回答
1
投票
不同之处在于,在setTimeout情况下,您正在preventDefault()回调中调用async,该回调中包含await -ed的Promise。当您等待Promise时,事件完成,此后将无法再通过preventDefault()进行拦截。
© www.soinside.com 2019 - 2024. All rights reserved.