JavaScript - 从多个数组填充对象构造函数

Posted

技术标签:

【中文标题】JavaScript - 从多个数组填充对象构造函数【英文标题】:JavaScript - populate object constructor from multiple arrays 【发布时间】:2020-10-30 08:25:06 【问题描述】:

我正在从一个网站收集多个内部文本属性,该网站在其页面上重复元素(24 个大学简介,包括名称、平均评分、课程数量等)。

我在一所大学使用querySelector() 测试了我的小程序,以收集我想要的4-5 innerText,使用var u = await Promise.allSettled([arr1, arr2, arr3, arr4, arr5]) 将它们组合在一起,并使用我在顶部定义的构造函数var currUniv = new University(...myArrayOfFacts)。到目前为止一切顺利(至少结果......)

由于该页面一次/在一个页面上提供 24 个大学项目(并且都在相同的结构中),我现在想使用 querySelectorAll() 一次抓取 5 个数组,每个数组包含 24 个元素。如果我坚持使用var u = await Promise.allSettled([arr1, arr2, arr3, arr4, arr5]),我最终会得到一个由 5 个数组组成的数组,现在不知道(而且似乎无法找到成功的 google 方法)我如何一次将每个数组的一个元素提供给我的构造函数。

我应该首先避免将所有东西都塞进一个大数组中吗? 我这样做是因为我认为我需要等待所有承诺来解决...... 或者我应该在什么时候开始循环遍历数组?

一切都是异步的。我稍微缩短了代码: 就像我进一步写的那样——对于一组 DOM 元素/一所大学来说效果很好。

非常感谢任何提示我正确的方向!

const puppeteer = require('./node_modules/puppeteer');

const startUrl = "https://www.studycheck.de/hochschulen/";

//constructor - shortend
function HSMain(name, ...)
      this.nameHS = name;
      this...


const hsfPageVisits = async () => 

  try
    const browser = await puppeteer.launch(headless: true);
    const page = await browser.newPage();
    await page.goto(startUrl, waitUntil: 'domcontentloaded');

   // get first element (name)
      var nameHS = await page.evaluate(() => 
        let name = Array.from(document.querySelectorAll('div .title a')).map(node => node.innerText);
        return name;
      );
   // get second element (rating)
      var rating = await page.evaluate(() => 
        let rate = Array.from(document.querySelectorAll('div .rating-container > div .rating-value')).map(node => node.innerText.trim());
      return rate;
      );
[...more DOM - elements...]

// wait for all promises to resolve
var univArr = await Promise.allSettled([nameHS, rating, ..., ..., ...]);

// spread the array into the object constructor
var myObj = await new HSMain(...univArr);

  await browser.close();
  
  catch(e)
    console.log("error", e);
  
;
hsfPageVisits();

【问题讨论】:

【参考方案1】:

所以你有一个名称数组和另一个用于评级等。这些数组的每个索引对应于同一所大学,因此只需map 其中一个数组并使用map 提供的索引从其余数组中获取值,不幸的是您不能在此处使用扩展语法:

let universities = nameHS.map((name, i) =>
    new University(name, rating[i], theNextArray[i], theArrayAfterThat[i], ...)
);

我的方法是一次获取每所大学的所有“事实”,而不是分别在不同的数组中。每所大学都会将其事实分组在一个对象或数组中,这将大大缩短代码,如下所示:

try 
    const browser = await puppeteer.launch( headless: true );
    const page = await browser.newPage();
    await page.goto(startUrl,  waitUntil: 'domcontentloaded' );

    var universitiesFacts = await page.evaluate(() => 
        let universities = Array.from(document.querySelectorAll(".institute-item")); // first get all university (each university info is contained in an element with a class 'institute-item')
        
        return universities.map(university => [                                      // for each .institute-item element
            university.querySelector(".title a").textContent.trim(),                 // get the name (using querySelector on the .institute-item element)
            university.querySelector(".rating-value").textContent.trim(),            // get the rating
            // ... the rest of facts for the current university
        ]);
    );

    let universities = universitiesFacts.map(facts => new University(...facts));     // now we can use the spread syntax
  
    await browser.close();

【讨论】:

以上是关于JavaScript - 从多个数组填充对象构造函数的主要内容,如果未能解决你的问题,请参考以下文章

javascript 从多个调用构造数组Array()。fill()。map()

JavaScript数组

JavaScript面向对象精要

JavaScript中的对象及其方法

JavaScript -- 内置对象数组

JavaScript 的 URL 对象是什么?