Вызов Axios API во вложенных циклах не возвращает ожидаемых результатов

#javascript #asynchronous #web-scraping #async-await #axios

#javascript #асинхронный #очистка веб-страниц #async-ожидание #axios

Вопрос:

Я использую Axios для извлечения данных продукта в формате JSON с веб-сайта. Приведенный ниже скрипт сначала запрашивает данные категории с сервера и перебирает три иерархии категорий, подкатегорий и (я предполагаю) подразделов. В третьем цикле параметр запроса вложенных подкатегорий используется в качестве параметра в вызове функции, который вызывает асинхронную функцию, которая использует этот параметр запроса для объединения с URL-адресом для создания нового URL-адреса, выполняет запрос GET для данных продукта, связанных с параметром запроса, и выполняет цикл до тех пор, пока переменная итерации pageCounter (которая используется в качестве параметра запроса разбивки на страницы, чтобы получить N страниц для каждого нового URL-адреса) не станет равной значению разбивки на страницы в текущем новом URL-адресе, содержащем вложенный URL-адрес. параметр запроса подкатегории.

     for (let i=0; i<obj.length; i  ) {
        let subcats = obj[i].subcategories.length;

        for(let n=0; n<subcats; n  ) {
            if(obj[i].subcategories[n].facetValueData) {
                let subsubcats = obj[i].subcategories[n].facetValueData.length

                for(let p=0; p<subsubcats; p  ) {
                    let productData = []
                    obj[i].subcategories[n].facetValueData[p].productData = productData
                    const scrapedData = await scrapeData(obj[i].subcategories[n].facetValueData.code)
                    obj[i].subcategories[n].facetValueData[p].productData.push(scrapedData)
                }
            } else {
                console.log(`No facet values present - ${obj[i].subcategories[n]}`)
            }
        }
    }
  

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

 async function scrapeData(queryParam) {

    var product = []
    var pagination;

      try {
          do {
            var nextPageLink = `currentPage=${pageCounter}amp;query=::cagCollectionPoint:Departure from Singapore:cagCategory:${queryParam}`
            var nextUrl = url.concat(nextPageLink)

            const response = await axios({
                method: "GET",
                url: nextUrl, 
                withCredentials: true,
                headers: headers
            })
            product = response.data["products"]
            pagination = response.data["pagination"]["totalPages"]
            pageCounter  ;

            //this logs all of the correct current queries
            console.log(response.data.currentQuery.query.value)

        } while (pageCounter<=pagination)

        return product

      } catch (error) {
          console.error(error)
      }
  }
  

На первый взгляд кажется, что он работает, поскольку он заполняет первые несколько объектов подкатегории массивом очищенных продуктов, однако некоторые из них не заполнены, т.Е. productData = []

Функция console log в функции scrapeData возвращает все правильные текущие запросы за итерацию, однако, когда они возвращаются, она возвращает только первые несколько ответов.

Я предполагаю, что массиву product нужно подождать? Но запрос axios уже ожидается, поэтому я не понимаю, почему это происходит.

Ответ №1:

Если я правильно понимаю ваше намерение относительно этого фрагмента кода:

 var product = [];
do {
    // ...
    const response = await axios(/* ... */);
    product = response.data["products"]
    // ...
} while (pageCounter<=1)
return product
  

похоже, что существует несколько страниц, и вы хотите поместить их все в массив product?

Но на самом деле на каждой странице вы заменяете массив product. Я бы предположил, что на пустых циклах ваша последняя выборка не дает результатов, и вы просто теряете все остальные из них.

Что вы, вероятно, хотите сделать, это просто изменить product = response.data["products"] на:

 product.push(...response.data["products"])
  

Комментарии:

1. Спасибо, я изменил свой код, как вы предложили, однако проблема все еще сохраняется, и только первые несколько (6, если быть точным, из 60) фактически добавляются в виде массивов к объекту json

2. откуда pageCounter берется? Моим первым предположением было бы то, что вы никогда не сбрасываете его обратно на ноль при переключении продуктов. Далее мне интересно, что происходит с вложенными циклами в функции, и когда вы вызываете эту функцию, вы await это делаете?

3. Спасибо, это был счетчик страниц, я вызывал его вне функции, спасибо, что прояснили это, мой мозг плавился от этого