流结束后调用的异步请求

时间:2015-08-21 14:08:03

标签: javascript node.js csv request

我遇到了nodeJS流媒体的问题。我遇到的问题是我的一个流我发送请求,使用请求模块(这是异步的),当请求得到响应时,整个流完成。

这是代码

var fs = require('fs');
var csv = require('fast-csv');
var path = require('path');
var request = require('request');
var JSONStream = require('JSONStream');
var locations = [];
var urls = [];
var MAP_QUEST_KEY = 'mykey';
var MAP_QUEST_URL = 'http://www.mapquestapi.com/geocoding/v1/address?key=' + MAP_QUEST_KEY + '&inFormat=json&json=';
var CSV_FILE_NAME = 'smaller_stores.csv';
var inFile = path.join(__dirname, 'input', CSV_FILE_NAME);
var outFile = path.join(__dirname, 'output', CSV_FILE_NAME);
// create a location object
var createLocationJSONStream = function (data) {
    var location = {
        street: data.street_no + ' ' + data.street_name,
        city: data.city_name,
        state: data.state_id
    };
    var url = MAP_QUEST_URL + JSON.stringify(location);
    // this request finishes after stream
    request({
        url: 'url',
        method: 'GET',
        json: location
    }, function (error, response, body) {
        if (error) {
            console.log(error);
        } else {
            data.lat = body.results[0].locations[0].latLng.lat;
            data.lng = body.results[0].locations[0].latLng.lng;
        }
        return data;
    });
};
var readFileStream = fs.createReadStream(inFile);
var writeFileStream = fs.createWriteStream(outFile);
var parseCsvStream = csv.parse({
    trim: true,
    headers: true,
    objectMode: false
});
var deserializeJSONStream = JSONStream.parse();
var streamingEvent = readFileStream.pipe(parseCsvStream).transform(createLocationJSONStream).pipe(deserializeJSONStream);
// eventually want to write out to csv
//.pipe(csv.createWriteStream({headers: true}))
//.pipe(fs.createWriteStream(outFile, {encoding: 'utf8'}));
streamingEvent.on('data', function (data) {
    console.log(JSON.stringify(data));
});
streamingEvent.on('end', function () {
    console.log('end');
});

这是输出:

end
200
application/json; charset=utf-8
200
application/json; charset=utf-8
200
application/json; charset=utf-8

以下是csv示例:

 region_id    region_name     street_no   street_name                sitetype_id      country_name    timezone_no     geocode_id      city_name               state_id    zip_code      county_name
3             West  350         ORCHARD AVE              N              USA 4   954824536      UKIAH                      CA            95482-4536    MENDOCINO
1             South 1000           4TH AVE                   N              USA 7   333041903      FORT LAUDERDALE          FL          33304-1903    BROWARD
0             Northeast 1370           HURFVILLE RD                N                USA 7   80963818       DEPTFORD                NJ           08096-3818    GLOUCESTER

我知道我正在处理错误的流,但不知道修复它的最简单方法是什么?管道到请求?

1 个答案:

答案 0 :(得分:1)

如果您希望在启动流代码之前完成异步request()操作,则需要将流代码INSIDE放入请求的完成回调中。这样,在您收到request()操作中的数据之前,您才能启动流代码。

此外,您无法像尝试执行return data;一样从异步操作返回值。从回调中返回数据只会返回到回调基础架构。外部函数早已返回,并且外部函数之后的后续代码行已经执行。相反,您必须在回调本身内部使用结果,或者从该回调中进行函数调用,并将数据传递给其他函数。

我并不完全遵循您尝试对流进行操作的内容,但如果您想确保request()操作之前完成var fs = require('fs'); var csv = require('fast-csv'); var path = require('path'); var request = require('request'); var JSONStream = require('JSONStream'); var locations = []; var urls = []; var MAP_QUEST_KEY = 'mykey'; var MAP_QUEST_URL = 'http://www.mapquestapi.com/geocoding/v1/address?key=' + MAP_QUEST_KEY + '&inFormat=json&json='; var CSV_FILE_NAME = 'smaller_stores.csv'; var inFile = path.join(__dirname, 'input', CSV_FILE_NAME); var outFile = path.join(__dirname, 'output', CSV_FILE_NAME); // create a location object var createLocationJSONStream = function (data) { var location = { street: data.street_no + ' ' + data.street_name, city: data.city_name, state: data.state_id }; var url = MAP_QUEST_URL + JSON.stringify(location); // this request finishes after stream request({ url: 'url', method: 'GET', json: location }, function (error, response, body) { if (error) { console.log(error); } else { // get the latLng position so we can use it in our streaming var position = body.results[0].locations[0].latLng; var readFileStream = fs.createReadStream(inFile); var writeFileStream = fs.createWriteStream(outFile); var parseCsvStream = csv.parse({ trim: true, headers: true, objectMode: false }); var deserializeJSONStream = JSONStream.parse(); var streamingEvent = readFileStream.pipe(parseCsvStream).transform(createLocationJSONStream).pipe(deserializeJSONStream); // eventually want to write out to csv //.pipe(csv.createWriteStream({headers: true})) //.pipe(fs.createWriteStream(outFile, {encoding: 'utf8'})); streamingEvent.on('data', function (data) { console.log(JSON.stringify(data)); }); streamingEvent.on('end', function () { console.log('end'); }); } }); }; 操作,那么他们会去哪里你做你的流:

position

latLng坐标现在可以在流代码中的任意位置的private String url = "http://www.hiddenlink.com/%s"; 变量中使用,并且在数据准备就绪之前,您的流操作不会启动。

仅供参考,我发现如果使用promises而不是普通的回调,任何涉及多个异步操作的代码最终都更容易编写,理解并执行强大的错误处理。这需要了解承诺是如何运作的,并且经常涉及“承诺”#34;一些操作(将常规异步操作转换为返回promise的操作)。所以,从长远来看,我建议你开始学习承诺。我使用Bluebird promise库进行node.js开发,因为它有很多有用的功能。