【问题标题】:Is there an async / Promise variant of the jQuery API?jQuery API 是否有异步/承诺变体?
【发布时间】:2019-11-01 21:55:24
【问题描述】:

我将 jQuery 的 .click() 包装在这个返回 Promise 的函数中:

async function clickPromise(selector) {
  return new Promise((resolve, reject) => {
    $(selector).click((event) => resolve(event));
  });
}

有没有更好的方法来让 jQuery 的回调 API 适应 Promises,而不是将它们全部包装在这些函数中?

【问题讨论】:

  • 我想通过使用 Promise 而不是回调来监听元素上的点击事件。
  • 1.你实际上想做什么?您给出的示例 not 完全等同于 jQuery click 方法 - 它只会解决一次这个承诺,所以它有点像 one,除了它也不支持相同的像one 一样的参数。 2. 为什么你要这样做?您要解决的问题是什么?
  • 未来可能多次发生的重复事件与一次性工具的 Promise 不匹配。如果您只寻找下一次点击而没有其他点击,您可以使用承诺,然后您也应该取消注册点击处理程序或使用.once()
  • DOM有.click(),它点击元素 - 这里jQuery的函数命名有点奇怪,click()实际上是on('click')的别名,绝对有一个普通的等价物,称为addEventListener。这不是讨厌 jQuery,而是“现代 JS 比 John 提出 jQuery 时的 JS 好多了”,而且很多 需要 jQuery 现在可以原生地工作,使用本地形式和约定,而不依赖于 3rd 方模式。而在这种情况下,事件监听的概念意味着像 Promise 这样的一次性处理程序实际上是没有意义的。

标签: javascript jquery asynchronous promise


【解决方案1】:

有没有更好的方法来让 jQuery 的回调 API 适应 Promises,而不是将它们全部包装在这些函数中?

首先,jQuery 已经包含一些对完成通知的承诺支持。例如,如果您想知道动画何时完成,他们有.promise(),它会在特定对象的 fx 动画队列完成时得到一个解决方案。这些类型的操作是一次性通知,非常适合 Promise 的工作方式。

jQuery 还内置了对 ajax 调用的 Promise 支持,您可以使用它们的回调接口或 jQuery ajax 的 Promise 接口。

jQuery 没有任何内置的 Promise 支持,因为它们不直接与 Promise 的一次性功能相匹配。

因此,如果您真的想在下一次点击特定元素时使用 Promise,那么您必须为此构建自己的 Promise 支持。

您提出的函数适用于某些输入参数:

function clickPromise(selector) {
  return new Promise((resolve, reject) => {
    $(selector).click((event) => resolve(event));
  });
}

例如,如果选择器只匹配一个 DOM 元素或者它匹配多个 DOM 元素,并且您只希望在任何这些元素上发生第一次点击,并且这些元素不会持续很长时间,因此您要调用它再用相同的元素(它会随着时间的推移建立事件侦听器),然后这可以正常工作。

就个人而言,如果你打算这样做,我建议这样做:

// Get promise for the very next click on any of 1 to many items
//    resolves when the first click happens
//    rejects if the selector doesn't match any elements
function clickPromise(selector) {
  return new Promise((resolve, reject) => {
    const items = $(selector);

    if (!items.length) {
        reject(new Error("selector empty"));
        return;
    }

    const handler = function(event) {
         // remove all event listeners we previously installed so they don't build up
         items.off('click', handler);
         resolve(event);
    }
    // install click handlers
    items.on('click', handler);
  });
}

与您的实现的主要区别在于,这会在单击发生时删除事件侦听器,因此如果在相同元素上反复使用它,它们不会随着时间的推移而建立,并且如果选择器与任何元素都不匹配,它会拒绝因为否则这将是一个永远不会解决的承诺。

仅供参考,这种类型的功能不依赖于 jQuery。再添加几行代码,您就可以使用普通的 DOM Javascript 实现相同的功能。


如果您一次只打算对一个元素使用它并且只传递一个与一个元素完全匹配的选择器,那么您可以使用.one() 使其更简单一些:

// Get promise for the very next click on any of 1 to many items
//    resolves when the first click happens
//    rejects if the selector doesn't match any elements
function clickPromise(selector) {
  return new Promise((resolve, reject) => {
    const items = $(selector);

    if (items.length === 0) {
        reject(new Error("selector empty"));
        return;
    } else if (items.length > 1) {
        reject(new Error("selector matches more than one element"));
        return;
    }

    items.one('click', function(event) {
        resolve(event);
    });
}

【讨论】:

    猜你喜欢
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-22
    • 2020-03-26
    • 1970-01-01
    • 2018-07-01
    相关资源
    最近更新 更多