@idx12x4xxx
Начинаю разбираться в JavaScript

Как выполнять цикл синхронно, если в нем асинхронная функция?

У меня есть цикл, в котором выполняется асинхронная функция в атрибут которой передается ссылка. Мне необходимо в начале каждой итерации цикла (всего 10 итераций) увеличивать значение последнего символа на единицу. Как сделать, чтобы новая итерация цикла начиналась только после выполнения асинхронной функции.

Пример кода (который не работает, т.к ссылки создаются быстрее чем выполняются функции):

for(let i = 1; i <= quanPage; i++){	  	
		
		let urlIter = urlSite + i; //Ссылка, которая создается с каждой новой итерацией
		
		needle.get(urlIter, function (err, res) { //Сама асинхронная функция
		    if (err) throw (err);
		    
			prodUrl = $('.product-card__link');  
			prodUrl.each(function (i, val) {    
		    	prodLink.push(urlSite + $(val).attr("href"));
			}); 
		});
	}

Пробовал через промисы, но ничего не работает, может не правильно их использовал.
  • Вопрос задан
  • 494 просмотра
Решения вопроса 1
sergiks
@sergiks Куратор тега JavaScript
♬♬
async / await
/**
 * асинхрота с запросом. Возвращает Promise
 */
const doAsyncStuff = (urlIter, urlSite) => new Promise((resolve, reject) => {
  needle.get(urlIter, (err, result) => { // Сама асинхронная функция
    if (err) reject(err);
    $('.product-card__link')
      .each((i, val) => prodLink.push(urlSite + $(val).attr("href")));

    resolve();
  })
})

/**
 * Тот самый цикл
 * @param {number} quanPage число страниц
 */
const doStuff = async quanPage => {
  for(let i = 1; i <= quanPage; i++) {
    let urlIter = urlSite + i; // Ссылка, которая создается с каждой новой итерацией
    await doAsyncStuff(urlIter, urlSite); // Ждём-с!
  }
}

doStuff(10);


Демо:
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
IDONTSUDO
@IDONTSUDO
ЧСВ программистов идет в комплекте с первой IDE.
for await (let line of lines){
console.log(lines[line])
}
// ES2018

в ES2018 есть возможность делать асинхронные итерации.
https://medium.com/@linus2228/javascript-%D1%87%D1...
Ответ написан
Комментировать
zkrvndm
@zkrvndm
Архитектор решений
Вместо for можно просто использовать функцию, которая циклически вызывает сама себя, пока счетчик удовлетворяет условиям:
i = 1;

function ciklotron() {

	if (i <= quanPage) {
		
		let urlIter = urlSite + i; 
		
		needle.get(urlIter, function (err, res) {
			if (err) throw (err);
			
		  prodUrl = $('.product-card__link');  
		  prodUrl.each(function (i, val) {    
				prodLink.push(urlSite + $(val).attr("href"));
		  });

		i = Number(i) + Number(1); // Увелчиваем счетчик на еденицу
		ciklotron(); // Вызываем сами себя
		  
		});

	}

}
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы