Задать вопрос
@Delor1th

Как сделать последовательное выполнение функций?

Имеется функция waitForElement, которая каждые checkInterval миллисекунд ищет элемент и, в случае успеха, прекращает поиск и, например, вызывает метод .click() у искомого элемента.
function waitForElementAndClick(selectors, checkInterval = 100) {
    let intervalId = setInterval(() => {
        if (document.querySelector(selectors) != null) {
            document.querySelector(selectors).click() 
            clearInterval(intervalId)  
        }
    }, checkInterval)
}

Однако, если вызвать эту функцию несколько раз для разных элементов, то независимо от порядка вызова функций метод .click() будет вызываться у первого найденного элемента.
function main() {
    waitForElementAndClick(".class1")
    waitForElementAndClick(".class2")
    waitForElementAndClick(".class3")
}

main()

То есть вызовы функций обрабатываются в стеке вызовов не последовательно, таким образом если на странице первым появится элемент, который можно найти по селектору .class2, то нажатие произойдёт, несмотря на то, что элемент с селектором .class1 ещё не был найден. Я пытался разобраться с асинхронностью, промисами, но у меня всё равно не хватает понимания, чтобы применить это к моему случаю. Мне необходимо, чтобы waitForElementAndClick(".class2") выполнялся только после завершения waitForElementAndClick(".class1"), как и waitForElementAndClick(".class3") только после завершения и waitForElementAndClick(".class1"), и waitForElementAndClick(".class2")
  • Вопрос задан
  • 482 просмотра
Подписаться 1 Средний Комментировать
Решения вопроса 1
zkrvndm
@zkrvndm
Архитектор решений
Это делается не так. Во первых, для поиска элементов на странице лучше использовать не таймеры, а MutationObserver. Во вторых, функцию кликер лучше оборачивать в промис и уже затем вызывать ее последовательно в том порядке в котором нужны клики. Ниже пример с одного из моих проектов:
Асинхронная функция кликер
async function main() {
    await clickElements('CSS-селектор 1');
    await clickElements('CSS-селектор 2');
    await clickElements('CSS-селектор 3');
}

main(); // Запускаем последовательные клики

function clickElements(selector, regexp, where) {
	
	return new Promise(function(returnResult) {
		
		var search_result = false;
		
		var local_reactive_function = function() {
			
			var click_elements = searchElements(selector, regexp, where);
			
			if (click_elements.length > 0) {
				
				if (search_result === false) {
					
					search_result = true;
					observer.disconnect(); 
					
					setTimeout(function() {
						
						var click_elements = searchElements(selector, regexp, where);
						
						for (var n = 0; n < click_elements.length; n++) {
							click_elements[n].click();
						}
						
						returnResult(click_elements.length);
						
					}, 500);
					
				}
				
			}
			
		}
		
		var observer = new MutationObserver(local_reactive_function);
		
		observer.observe(document.body, {
			characterData: true,
			attributes: true,
			childList: true,
			subtree: true
		});
		
		local_reactive_function();
		
	});
	
}

function searchElements(selector, regexp, where) {

	var search_elements = [];
	
	if (typeof where !== 'undefined') {
		
		var all_elements = where.querySelectorAll(selector);
		
	}
	
	else {
		
		var all_elements = document.querySelectorAll(selector);
		
	}
	
	for (var n = 0; n < all_elements.length; n++) {
		
		if (typeof regexp == 'object') {
			
			if (typeof regexp.test == 'function') {
				
				if (regexp.test(all_elements[n].innerText.trim())) {
					
					search_elements.push(all_elements[n]);
					
				}
				
			}
			
			
		}
		
		else {
			
			search_elements.push(all_elements[n]);
			
		}
	}
	
	return search_elements;

}

Функция clickElements обязательно дождется появления кнопок соотвествующих указанным CSS-селекторам и только тогда их нажмёт, последовательно сверху вниз. При этом в эту функцию вторым параметром можно передать регулярное выражение, чтобы найти кнопку по его тексту. Третьим параметрим, при желании, можно указать узел внутри котрого надо искать элемент.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
WblCHA
@WblCHA
function waitForElementAndClick(selectors, checkInterval = 100) {
  return new Promise((resolve) => {
    let intervalId = setInterval(() => {
        if (document.querySelector(selectors) != null) {
            document.querySelector(selectors).click() 
            clearInterval(intervalId)  
            resolve()
        }
    }, checkInterval)
  });
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы