Существует ли асинхронный / Promise вариант jQuery API? - PullRequest
0 голосов
/ 02 ноября 2019

Я обернул jQuery .click() в эту функцию, которая возвращает Обещание:

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

Есть ли лучший способ адаптировать API обратного вызова jQuery к Обещаниям, чем оборачивать их всех в эти функции?

Ответы [ 2 ]

2 голосов
/ 02 ноября 2019

Есть ли лучший способ адаптировать API обратного вызова jQuery к Promises, чем оборачивать их всех в эти функции?

Во-первых, jQuery уже содержит некоторую поддержку обещаний для уведомления о завершении. Если, например, вам интересно знать, когда анимация завершена, у них есть .promise(), которая получает обещание, которое разрешается, когда очередь анимации FX для определенного объекта выполнена. Эти типы действий представляют собой однократные уведомления, которые хорошо соответствуют тому, как работают обещания.

jQuery также имеет встроенную поддержку обещаний для вызовов ajax, и вы можете использовать их интерфейс обратного вызова или интерфейс обещаний для jQuery. ajax.

jQuery не имеет встроенной поддержки обещаний для вещей, которые могут повторяться (например, нажатия кнопок), поскольку они не совпадают с возможностью одноразовых обещаний.

Итак, если вы действительно хотите использовать обещание для следующего щелчка по определенному элементу, вам придется создать собственную поддержку обещаний для этого.

Функция, которую вы предложили, работает для некоторыхвходные параметры:

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. С помощью еще нескольких строк кода вы можете создать ту же функциональность с простым Javascript DOM.


Если вы когда-либо собираетесь использовать это только для одного элемента за раз и пропустите только селектор, который соответствуетровно один элемент, тогда вы можете использовать .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);
    });
}
0 голосов
/ 02 ноября 2019

Вы можете использовать объект jquery $deferred, эквивалентный Promises.

https://api.jquery.com/category/deferred-object/

Из документов:

// Existing object
var obj = {
    hello: function( name ) {
      alert( "Hello " + name );
    }
  },
  // Create a Deferred
  defer = $.Deferred();

// Set object as a promise
defer.promise( obj );

// Resolve the deferred
defer.resolve( "John" );

// Use the object as a Promise
obj.done(function( name ) {
  obj.hello( name ); // Will alert "Hello John"
}).hello( "Karl" ); // Will alert "Hello Karl"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...