Есть ли лучший способ адаптировать 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);
});
}