0

I have a node.js script in which I make a rest request (a GET request in this case). The output shows up in the console just fine when I run the script from the command line. I want to display the output to an html page (in other words - I want to eventually run this script from web web page).

I have created two node.js scripts - one for the rest request and one to direct the output to an html page.

rest request script:

const request = require('request-promise')
const readline = require('readline')

const options = {
    method: 'GET',
    uri: 'http://dummy.restapiexample.com/api/v1/employees'
}
request(options)
    .then(function (response) {
        // Request was successful, use the response object at will
        json: true
        //console.dir(response)
        JSON.parse(response)
        console.dir((JSON.parse(response)), {depth: null, colors: true})

    })
    .catch(function (err) {
        // Something bad happened, handle the error
    })

let currentResult = request

outputResult(currentResult);
function outputResult(result) {
    currentResult = (request);
}

output director to html page:

const restProto = document.getElementById('protocol');
const apiToTest = document.getElementById('uri');
const testApiResult = document.getElementById('output');

const currentResultOutput = document.getElementById('output');

function outputResult(result) {
    currentResultOutput.textContent = result;
}

Here is the html page I am trying to direct to:

<!DOCTYPE html>
<html>
<body>
<head>
<meta name="viewport" content="width=device-width" initial-scale=1" charset="UTF-8">
<style>
    .collapsible {
        background-color: white;
        color: black;
        cursor: pointer;
        padding: 1px;
        border: none;
        text-align: left;
        outline: none;
        font-size: 15px;
    }

    .active, .collapsible:hover {
        background-color: #f1f1f1;
    }

    .content {
        padding: 0 18px;
        display: none;
        overflow: hidden;
        background-color: #f1f1f1;
    }
</style>
</head>

<h2>API Test (v 0.1 alpha)</h2>

<form>
    <label for="protocol">protocol</label>
    <select name="restcall" id="protocol">
        <option value="get">GET</option>
        <option value="put">PUT</option>
        <option value="post">POST</option>
        <option value="delete">DELETE</option>
    </select> &nbsp;&nbsp;

    <label for="uri">  url: </label>
    <input type="text" id="uri" name="uri">
    <br><br>

    <button class="collapsible">Advanced</button>
    <div class="content">
        <br>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit,
            sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
            Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
            commodo consequat.</p><br>
    </div>

    <br><br>
    <input type="submit" value="Send">
    <br><br>

</form>

<textarea id="output" name="output" rows="20" cols="50">
    Response displays here ...
</textarea>

<script>
    var coll = document.getElementsByClassName("collapsible");
    var i;

    for (i = 0; i < coll.length; i++) {
        coll[i].addEventListener("click", function() {
            //this.classList.toggle("active");
            var content = this.nextElementSibling;
            if (content.style.display === "block") {
                content.style.display = "none";
            } else {
                content.style.display = "block";
            }
        });
    }

</script>

<script src="./apitest2.js"></script>
<script src="./apitest3.js"></script>
<script src="./responseDirector.js"></script>

</body>
</html>

What am I missing to make this code work?

ironmantis7x
  • 807
  • 2
  • 23
  • 58
  • Several things. 1. I'm surprised this code executes at all, because `json: true` in the middle of a callback function is invalid syntax. You should get a crash at runtime. 2. `let currentResult = request` just copies the `request` module in a new variable. 3. `currentResult = (request)` just copies the `request` module in a new variable... with parenthesis :) 4. Your fetch function is asynchronous, you get its result in the `.then`, but you do nothing with it. You only `console.dir` it, then dead end. – Jeremy Thille Jul 08 '20 at 09:44
  • Also I don't understand `I want to direct the output to an html page.` What do you mean `direct`? What does "directing a page" mean? – Jeremy Thille Jul 08 '20 at 09:45
  • @JeremyThille thank you fo rthe response. Is it possible you can show me how to fix my code? I am a newbie at nodeJS. I have taken some online classes, but experience is the best teacher. Any instruction you can give me is much appreciated. – ironmantis7x Jul 08 '20 at 09:47
  • @JeremyThille : i want to display the out put to an html page. In other words, the intention is to run this script through an html page. – ironmantis7x Jul 08 '20 at 09:48
  • Yep, writing an anser now. Give me a minute – Jeremy Thille Jul 08 '20 at 09:50

2 Answers2

0

I believe you are trying to load an HTML page from Node, then load the received HTML like in a browser to access its DOM elements? That's a typical web scraping scenario.

No offense but your code is so globally wrong (which is normal when you learn) that I can't just correct all its mistakes, I think it's faster to rewrite it all :)

import * as cheerio from 'cheerio';
const axios = require('axios').default; // "request" is a deprecated package. Use Axios instead.

const fetchHTML = async(url) => {

    const options = {
        url,
        timeout: 10000,
        responseType: 'text',
    };

    let response;

    try {
        response = await axios(options);
    } catch {
        // Error management here
    }

    return response.data
}

(async() => { // because "await" can only be used inside an async function. This is a little trick to make one

    const html = await fetchHTML('http://dummy.restapiexample.com/api/v1/employees');

    const $ = cheerio.load(html); // Cheerio is a server-side version of jQuery core. This loads the HTML text as a DOM, now you can access its HTML nodes with jQuery

    const restProto = $('#protocol');
    const apiToTest = $('#uri');
    const testApiResult = $('#output');

    console.log(restProto, apiToTest, testApiResult);
})

EDIT : AAAAAH I just noticed that you're fetching JSON data from an API, not an HTML page!

So what you are trying to do is GENERATE an HTML page from a fetched JSON! Meaning; you want to WRITE what you received from the API in an HTML page! That's what you mean by "directing" a page. So that's different, you need a templating engine. For instance; with Pug, it would be something like :

myTemplate.pug :

doctype html
html
    body
        h2 API Test (v 0.1 alpha)

        textarea#output
            | #{json}

        script(src="./apitest2.js")
        script(src="./apitest3.js")
        script(src="./responseDirector.js")

And your script :

const axios = require('axios').default;
const pug = require('pug');

const fetchJSON = async(url) => {
    const options = { url, timeout: 10000 };

    let response;

    try {
        response = await axios(options);
    } catch {
        // Error management here
    }

    return response.data
}

(async() => {

    const json = await fetchJSON('http://dummy.restapiexample.com/api/v1/employees');

    const html = pug.renderFile("myTemplate.pug", json); // Pass your data to Pug

    // Do what you want with your rendered HTML.
})
Jeremy Thille
  • 26,047
  • 12
  • 43
  • 63
  • when I try to run this solution you provided for the answer (thanks by the way!) I get the following error: import * as cheerio from 'cheerio'; ^^^^^^ SyntaxError: Cannot use import statement outside a module Any ideas??? – ironmantis7x Jul 08 '20 at 15:49
  • does this code replace my responseDirector.js code?? – ironmantis7x Jul 08 '20 at 16:51
  • https://stackoverflow.com/questions/58384179/syntaxerror-cannot-use-import-statement-outside-a-module – Jeremy Thille Jul 09 '20 at 14:13
  • I have no idea what `responseDirector.js` does :) I'm just generating the HTML – Jeremy Thille Jul 09 '20 at 14:14
  • that file was intended to push the output of the node script to the HTML page. Looks like the responseDirector.js script is not needed. Can you tell me how to use the file you wrote in your answer? Do i need to change the html file as well?? – ironmantis7x Jul 09 '20 at 21:07
  • I told you how to generate an HTML page using the JSON data you get from an API (using a templating engine). Now you have your HTML page (in a variable). You can do whatever you want with it, either send it back to the client (`res.send(html)`), write it to a file (`fs.writeFile("page.html",html)`, etc. – Jeremy Thille Jul 10 '20 at 06:03
  • Thanks Jeremy. I am running my server using npm start and it's still rendering the old html page. I don't know how to get the server to see the pug file and execute that. – ironmantis7x Jul 10 '20 at 10:04
0

I was able to solve the issue using parcelJS. It elimated the need for a back end and I could get the out put to be displayed to an html page that parcel generated.

details of parcel is here

ironmantis7x
  • 807
  • 2
  • 23
  • 58