首页 > 解决方案 > 有没有办法干净地创建一个在鼠标左键向上或向下后解决的承诺?

问题描述

在我的客户代码中,我有

const whatMouseDid = await mouseDoesSomething()

后一个函数看起来像:

async mouseDoesSomething() {
    const mouseUp = (resolve) => {
        const handler = (evt) => {
            if (evt.button === 0)
                resolve("up")
        }
        return handler
    }
    const mouseDown = (resolve) => {
        const handler = (evt) => {
            if (evt.button === 0)
                resolve("down")
        }
        return handler
    }
    return new Promise((resolve, reject) => {
        document.addEventListener('mouseup', mouseUp(resolve))
        document.addEventListener('mousedown', mouseDown(resolve))
    })
}

这已经比我希望的要复杂一些,但仍然可以管理。但是,有一个问题 - 侦听器永远不会被删除。而且因为我需要传递对 的引用Promise.resolve,所以我不removeEventListener容易。我能想到的唯一方法是保留一个可变的处理程序列表以及分配给它们的事件、目标等,并在处理程序函数中迭代该列表并删除附加的处理程序。可选参数{once: true}也不起作用,因为如果单击的按钮不是我想要的,我无法解决。

这一切都让人感觉非常复杂,让我觉得我只是错过了明显的简单方法;我是吗?还是真的有这么多麻烦?

标签: javascriptecmascript-6es6-promise

解决方案


而且因为我需要传入对 Promise.resolve 的引用,所以我不能轻易地删除EventListener。我能想到的唯一方法是保留一个可变列表

为什么这么复杂?您在 Promise 执行器中创建函数,只需引用它们。

mouseDoesSomething() {
    return new Promise((resolve, reject) => {
        const mouseUphandler = evt => {
            if (evt.button === 0) {
                resolve("up")
                document.removeEventListener('mouseup', mouseUpHandler)
                document.removeEventListener('mousedown', mouseDownHandler)
            }
        }
        const mouseDownhandler = evt => {
            if (evt.button === 0) {
                resolve("down")
                document.removeEventListener('mouseup', mouseUpHandler)
                document.removeEventListener('mousedown', mouseDownHandler)
            }
        }
        document.addEventListener('mouseup', mouseUpHandler)
        document.addEventListener('mousedown', mouseDownHandler)
    })
}

当然这是很多代码重复,但是您可以通过动态创建处理程序来再次抽象它 - 您只需要在声明两个处理程序的范围内执行它:

mouseDoesSomething() {
    return new Promise((resolve, reject) => {
        const makeHandler = dir => evt => {
            if (evt.button === 0) {
                resolve(dir)
                document.removeEventListener('mouseup', mouseUpHandler)
                document.removeEventListener('mousedown', mouseDownHandler)
            }
        }
        const mouseUphandler = makeHandler("up")
        const mouseDownhandler = makeHandler("down")
        document.addEventListener('mouseup', mouseUpHandler)
        document.addEventListener('mousedown', mouseDownHandler)
    })
}

推荐阅读