I want to return an array in a Promise object, but I want to return it after processing the array before that.

const makeAgenda = (cheerio_object) =>{
  return new Promise ((resolve, reject) =>{
    console.log ("In makeAgenda");
    const $= cheerio_object;
    const agenda = [];
    $('div.article-main section'). map ((i, node) =>{
      return $(node) .find ('h2'). map ((i, h2) =>{
        const array = {
          "h2": $(h2) .text (),
          "h3": []
        const count = $(node) .find ('h3');
        if (count.length>= 1) {
          $(node) .find ('h3'). map ((i, h3) =>{
            return array.h3.push ($(h3) .text ());
        return agenda.push (array);
    resolve (agenda);

cheerio_object means cheerio When handling html above, it can be handled like jQuery.

I would like to define an array called

agenda, extract h2 and h3 elements from html, create a table of contents array, and return it.

In the current code, agenda returns unprocessed.
I am in the midst of acclaimed learning about Promise, but I am in trouble because I cannot solve it. When doing an array, or map, I found a good article using Promise.all, but I couldn't realize what I wanted to do. .

I want you to give me instructions.

  • Answer # 1

    How did Agenda verify that it was unprocessed?
    Although there are places where I feel that the code is suspicious, it seems to move, but ...
    Well, even if there is a problem, I think that it will be solved normally if you learn how to use the cheerio method a little more.

    And cheerio's map method is synchronous, so it doesn't require a promise or rather a hindrance.
    I think that the cause is likely to be the usage outside this.

    Description of map based on the above

    In addition to the meaning of map,
    It means that the product is made by pressing the template from the top at the factory.
    Map in programming is the latter meaning, which means that all the elements of the array are assigned a function that converts A → B, and another array with the same number of elements is recreated.
    If you look for it, JavaScript, PHP, Ruby, Python, Haskell, Elixir… etc.

    Look at this point of view.
    For example, the return value of[]. Push (123)is not[123]but1, which is the number of elements in the new array. Is it suitable for the movement of the map?

    If you want to rewrite this process as an axis, use each.
    This translates to "each" when translated into Japanese, and is not thought of as a return value.
    The following is a rewrite of each axis. I haven't verified it, but I think it has a nice code.

    ※ Promise? Delete immediately because it is a synchronous function

    // If you want to create a function that takes a string as an argument, name it string? Is n’t that right?
    // Put in parentheses and write in Haskell style notation
    // makeAgenda :: CheerioObject->Object
    const makeAgenda = $=>{
      // Since it became an A to B function instead of a Promise, I don't need console.log
      const agenda = [];
      // Accept arguments that are not used as convention by `_`
      $('div.article-main section'). each ((_, node) =>
        agenda.push ({
          'h2': $(node) .find ('h2'). text (),
          // Isn't this the place where the map is used?
          'h3': $(node) .find ('h3'). map ((_, h3) =>$(h3) .text ()). get ()
      return agenda;

  • Answer # 2

    The code appears to match. I triedmakeAgendaas it is, but it seems to be able to get it properly.

    const cheerio = require ('cheerio')
    makeAgenda (cheerio.load (`
    <div class = 'article-main'>
    <h2>Hello world1</h2>
    <h3>Hello world2</h3>
    <h3>Hello world3</h3>
    <div class = 'article-main'>
    <h2>Hello world4</h2>
    <h3>Hello world5</h3>
    <h3>Hello world6</h3>
    `)). then (r =>(console.log (r)})


    >[{h2: 'Hello world1', h3: ['Hello world2', 'Hello world3']},
      {h2: 'Hello world4', h3: ['Hello world5', 'Hello world6']}]

    Maybe there is no expected element in the target HTML? (class ='article-main'etc.)