1

I have the following server.js get route

app.get('/', function(req, res) {
var url;
var final_res = [];
endpoints.forEach(function(url){
    request(url, function(error,response,body){
        if(!error && response.statusCode == 200){
            final_res.push(url.url);
            console.log(url.url);
        }else{
            res.send(err);
            console.log(err);
        }
    });
});
});

And this is my client js where I fetch this exact same get with jQuery

$(document).ready(function() {
$.get('http://localhost:3000/', function(data) {
    console.log(data);
    $("#body").text(data);
});
});

When I open my index.html it displays the user interface correctly and inside my terminal where I have executing my server.js it correctly displays the url. What I can't accomplish is how to use my data that my jQuery receives in order to populate a table inside my html. My table will be populated with urls that are fetch from my endpoints.

I have some background in nodejs but I cant wrap this up.

2 Answers 2

2

Since you need to know when multiple requests are done, I'd suggest you switch to using the request-promise library so you can use promises to track when all the requests are done. That library also checks the statusCode for you automatically. So, you can do this:

const rp = require('request-promise');

app.get('/', function(req, res) {
    Promise.all(endpoints.map(url => {
        return rp(url).then(r => {
            return url.url;
        }).catch(err => {
            // rather than error, just return null result
            return null;
        })
    })).then(results => {
        // filter out null values, then send array as the response
        res.json(results.filter(item => item !== null));
    }).catch(err => {
        console.log(err);
        res.sendStatus(500);
    });
});

This will run all the requests in parallel, but collect the results in order which should result in the fastest overall run time.

If you wanted to run them one a time, you could use async/await like this:

const rp = require('request-promise');

app.get('/', async function(req, res) {
    let results = [];
    for (let url of endpoints) {
        try {
            let r = await rp(url);
            if (r) {
                results.push(url.url);
            }
        } catch(e) {
            // ignore error
        }
    }
    res.json(results);
});

EDIT Jan, 2020 - request() module in maintenance mode

FYI, the request module and its derivatives like request-promise are now in maintenance mode and will not be actively developed to add new features. You can read more about the reasoning here. There is a list of alternatives in this table with some discussion of each one. I have been using got() myself and it's built from the beginning to use promises and is simple to use.

Sign up to request clarification or add additional context in comments.

4 Comments

Awesome it look cleaner using promises the only issue I'm having now is I'm getting a CORS error: Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at localhost:3000. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). I dont understand why if my node is making the request and im only calling my endpoint that fetches this information @jfriend00
@user2737948 - Are you getting the CORs error in the browser? If so, what does the browser show in the URL bar for the page where you're making the ajax request?
I open my index in another window and is pointing out the the address from my documents. Is it necessary to have my index inside my nodejs server?
@user2737948 - You did not answer either of the questions I asked in my previous comment and I have no idea what your last comment means. If you want to make an Ajax call to http://localhost:3000, then you need to also load the web page from that same server so that the URL in the browser starts with http://localhost:3000. If you are loading the web page from the file system directly, you cannot do Ajax to http://localhost:3000.
0

You must wait for all requests gets resolved to then send final_res array back to client. You can do this using async/await and Promise.all concepts. If you don't want to use these resources then you'll need to count and wait all request manually, using a counter to know when all requests has done, as below:

app.get('/', function(req, res) {
    var url;
    var final_res = [];
    var respCounter = endpoints.length;
    endpoints.forEach(function(url){
        request(url, function(error,response,body){
            respCounter--;
            if(!error && response.statusCode == 200){
                final_res.push(url.url);
                console.log(url.url);
            }else{
                res.send(err);
                console.log(err);
            }
            if(respCounter == 0) {
                res.send(final_res);
            }
        });
    });
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.