【问题标题】:How to make synchronous http call using Promises in Nodejs如何在 Nodejs 中使用 Promises 进行同步 http 调用
【发布时间】:2016-07-30 11:59:49
【问题描述】:

我想使用 Q Promises 同步进行 http 调用,我有 100 名学生,我需要他们每个人从另一个平台获取一些数据,并通过 Q Promises 尝试这样做,但看起来不像正在同步进行。

如何确保在完成解析响应并插入 mongodb 后不会进行另一个调用:

到目前为止,我的代码如下所示:

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;
}

谁能告诉我我需要做什么才能实现这些目标? 是否也有可能让我知道所有的 http 调用何时完成并且所有的插入都完成了......

【问题讨论】:

  • 如果你想一个接一个地处理一个学生,使用eachSeries而不是eachcallback,这是iteratee的第二个参数。处理结束时调用callback
  • 对不起,我是回调、承诺的新手,我该怎么做?我在哪里添加它?
  • @DimaFitiskin 我更新了我的代码,你的意思是这样,添加回调?

标签: javascript node.js promise q


【解决方案1】:

我会放弃您当前的方法并使用 npm 模块 request-promise。 https://www.npmjs.com/package/request-promise

非常流行和成熟。

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) {
});

现在您只需将其转换为您想要的 100 个请求的某种迭代,即可完成工作。

【讨论】:

  • 我看到了这个库,它看起来很棒,但我只是不知道如何让我的代码使用它。我不知道如何将它转换为某种迭代:s,可以你给我一个例子,那我可以试试……
  • 好的,给我一个 3 个 URL 的例子,这样我就可以看到它们在哪里相似以用于迭代目的。
  • 网址无关紧要,你可以写任何网址,我只是想看看你将如何将其转换为 foreach 或 smth... 那么我可以看到。
  • 对不起,我正在下载一些大的东西,我的机器很慢 - 我没有时间做你想做的事,但我建议看看 stackoverflow.com/questions/25263723/…bluebirdjs.com/docs/api/promise.each.html 让你开始
  • 实际上我会再考虑一下,我会花一些时间来做这件事 - 我会做一个 plunkr 并在它完成时给你一个链接:)
猜你喜欢
  • 1970-01-01
  • 2016-12-16
  • 1970-01-01
  • 2014-08-23
  • 1970-01-01
  • 2019-07-03
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多