Lulzim Fazlija
Lulzim Fazlija

Reputation: 885

How to make synchronous http call using Promises in Nodejs

I would like to make http call synchronously using Q Promises, I have 100 students that I need for each of them to take some data from another platform and to do that I was trying via Q Promises but it does not seem like it is doing synchronously.

How do I make sure that another call is not being made once one is finished with parsing it's response and insertion into mongodb:

my code so far looks like this:

var startDate = new Date("February 20, 2016 00:00:00");  //Start from February
var from = new Date(startDate).getTime() / 1000;
startDate.setDate(startDate.getDate() + 30);
var to = new Date(startDate).getTime() / 1000;

iterateThruAllStudents(from, to);

function iterateThruAllStudents(from, to) {
    Student.find({status: 'student'})
        .populate('user')
        .exec(function (err, students) {
            if (err) {
                throw err;
            }

           async.eachSeries(students, function iteratee(student, callback) {
                    if (student.worksnap.user != null) {
                        var worksnapOptions = {
                            hostname: 'worksnaps.com',
                            path: '/api/projects/' + project_id + '/time_entries.xml?user_ids=' + student.worksnap.user.user_id + '&from_timestamp=' + from + '&to_timestamp=' + to,
                            headers: {
                                'Authorization': 'Basic xxxx='
                            },
                            method: 'GET'
                        };

                        promisedRequest(worksnapOptions)
                            .then(function (response) { //callback invoked on deferred.resolve
                                parser.parseString(response, function (err, results) {
                                    var json_string = JSON.stringify(results.time_entries);
                                    var timeEntries = JSON.parse(json_string);
                                    _.forEach(timeEntries, function (timeEntry) {
                                        _.forEach(timeEntry, function (item) {
                                            saveTimeEntry(item);
                                        });
                                    });
                                });
                                callback();
                            }, function (newsError) { //callback invoked on deferred.reject
                                console.log(newsError);
                            });
                    }
                });

function saveTimeEntry(item) {
    Student.findOne({
            'worksnap.user.user_id': item.user_id[0]
        })
        .populate('user')
        .exec(function (err, student) {
            if (err) {
                throw err;
            }
            student.timeEntries.push(item);
            student.save(function (err) {
                if (err) {
                    console.log(err);
                } else {
                    console.log('item inserted...');
                }
            });

        });
}

function promisedRequest(requestOptions) {
    //create a deferred object from Q
    process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
    var deferred = Q.defer();
    var req = http.request(requestOptions, function (response) {
        //set the response encoding to parse json string
        response.setEncoding('utf8');
        var responseData = '';
        //append data to responseData variable on the 'data' event emission
        response.on('data', function (data) {
            responseData += data;
        });
        //listen to the 'end' event
        response.on('end', function () {
            //resolve the deferred object with the response
            console.log('http call finished');
            deferred.resolve(responseData);
        });
    });

    //listen to the 'error' event
    req.on('error', function (err) {
        //if an error occurs reject the deferred
        deferred.reject(err);
    });
    req.end();
    //we are returning a promise object
    //if we returned the deferred object
    //deferred object reject and resolve could potentially be modified
    //violating the expected behavior of this function
    return deferred.promise;
}

Anyone could tell me what do I need to do to achieve such things? Is it also possible so that I know when all of the http calls are finished and the insertion is done for all...

Upvotes: 2

Views: 4384

Answers (1)

danday74
danday74

Reputation: 57195

I would abandon your current approach and use the npm module request-promise. https://www.npmjs.com/package/request-promise

It's very popular and mature.

rp('http://your/url1').then(function (response1) {
    // response1 access here
    return rp('http://your/url2')
}).then(function (response2) {
    // response2 access here
    return rp('http://your/url3')
}).then(function (response3) {
    // response3 access here
}).catch(function (err) {
});

Now you just need to convert this to some kind of iteration for the 100 requests you want and the job will be done.

Upvotes: 2

Related Questions