ton1
ton1

Reputation: 7628

Node.js res.render when task completed

I'm making Node.js Application using Express.js. I have a page which render some datas from other site. so I use with Cheerio.js and It's not problem, but the problem is I don't know how can I render when the scrapping task completed. I made a code like below, Please see.

var urls = [ 'http://a.com/fruits', 'http://a.com/cars', 'http://a.com/toys' ] 

function getData(){

// get html and parse, return some data.
  ...       
}

var data_set = '';

for (var i=0; i< urls.length ; i++){
     data_set += getData(urls[i]);
}

// When get all data, render <------ How can I catch when?
res.render('some_page', { data : data_set });

Thought some ways to do it,

#1 - Render when i == urls.length

for (var i=0; i< urls.length ; i++){
     data_set += getData(urls[i]);
     if( i == urls.length){
        res.render(....);
     }
}

// Result : 
// The data has not been scrapped, so the page wouldn't display data fully. 

#2 - callback with getData()

function getData(callback){

// get html and parse, return some data.
  ...
// when complete, callback();          
}

var someHelper = 0;
getData(function(){ someHelper ++ ;});

if (someHelper == 3){
    res.render(...);
}

// If someHeper is not 3, the page would not rendered. 
// And `if statement` executed before someHelper == 3 at times ==> infinite page loading (error)

How can I handle this? Should I find use Promise?... Please Help me with some points.

Upvotes: 0

Views: 1657

Answers (2)

wwwggxk
wwwggxk

Reputation: 1

Nested callbacks may help you. You can call the getData function one by one, and append content to data_set in each callback function.

var urls = [ 'http://a.com/fruits', 'http://a.com/cars', 'http://a.com/toys' ], data_set = '';

function getData(url, cb){

    // get html and parse, return some data.
      ...
    // call cb when downloaded contents
    cb(content);

}

getData(urls[0], function (content) {

    data_set += content;
    getData(urls[1], function (content) {

        data_set += content;
        getData(urls[2], function (content) {
            data_set += content;
            res.render('some_page', { data : data_set });
        }

    }

});

To avoid callback hell, you can also use module like "async", "q", "promise".

Upvotes: 0

Dmitry Matveev
Dmitry Matveev

Reputation: 5376

you should use either promises or async.js library up to you really...

here is how you could do it using promises

function getData(urlString) {
   return new Promise(function (res, rej) {
      //fetch and resolve promise with data from urlString
   });
}

var data_set = '';
var promises = [];
for (var i=0; i< urls.length ; i++){
    promises.push(function () {
        return getData(urls[i]).then(function (data) {
            data_set += data;
        });
    });
}

Promise.all(promises).then(function () {
    res.render('some_page', { data : data_set });
});

Upvotes: 2

Related Questions