javascript - 可能的嵌套异步函数

标签 javascript node.js parsing asynchronous

所以我在这里阅读了很多关于异步函数的不同答案,但我认为我过度思考了我的问题,或者我已经盯着它看了太久,但我无法弄清楚。因此,非常感谢您的帮助。

所以我正在解析一个 csv 文件,然后尝试通过另一个 api 获取纬度/经度。但我无法访问函数之外的纬度/经度。下面是我的代码,我已尽我所能对其进行评论,如果有任何问题或更好的方法,请告诉我。

谢谢

var location = [] 
function run() {
    http.get(url, function(res) {
        if(res.statusCode === 200) {
            res.pipe(parse(function(err, data) {
                for(i = 1; i < data.length; i++) {
                    var info = data[i];
                    passLoc = info[6].replace('block ', '')
                    passLoc = passLoc.replace(/ /g, "+")
                    getLoc(passLoc, function(loc) {
                        location.push(loc);
                        //If I console.log(location) here I get all the info I want but.....it is printed 100 times becuase it is printed for each i in data.length
                    })
                }
                console.log(location) // loging this here gives me an empty array           
            }))
        }else {
            console.error('The address is unavailable. (%d)', res.statusCode);
        }
    })
}
function getLoc(x, callback) {
    var url = "http://geodata.alleghenycounty.us/arcgis/rest/services/Geocoders/EAMS_Composite_Loc/GeocodeServer/findAddressCandidates?Street=" + x + "&City=Pittsburgh&State=PA&ZIP=&SingleLine=&outFields=&outSR=4326&searchExtent=&f=pjson";
    http.get(url, function(res) {
        var data = '';
        res.on('data', function(chunk) {
            data += chunk;
        });
        res.on('end', function() {
            var d = JSON.parse(data);
            var obj = d.candidates;
            if(obj != '') {
                var loc = obj[0].location
                    var lat = loc.x
                    var lng = loc.y
                    var location = [lat, lng];
                callback(location)
            } else {
                callback(x);
            }
        });
        res.on('error', function(err) {
            callback("error!")
        });
    });
}

最佳答案

您的代码尝试 synchronously consume asynchronous data -- 在任何异步操作完成之前,您正在尝试同步访问结果(位置)。

由于您有多个并行运行的异步操作,因此您可以使用 async.parallel帮助控制异步流程:

var async = require('async');

function run() {
    http.get(url, function(res) {
        if(res.statusCode === 200) {
            res.pipe(parse(function(err, data) {
                // array of async tasks to execute
                var tasks = [];

                data.slice(1).forEach(function(info) {
                    var passLoc = info[6].replace('block ', '').replace(/ /g, '+');

                    // push an async operation to the `tasks` array
                    tasks.push(function(cb) {
                        getLoc(passLoc, function(loc) {
                            cb(null, loc);
                        });
                    });
                });

                // run all async tasks in parallel
                async.parallel(tasks, function(err, locations) {
                    // consume data when all async tasks are finished
                    console.log(locations);
                });
            }));
        }else {
            console.error('The address is unavailable. (%d)', res.statusCode);
        }
    });
}

此外,for 循环不会创建作用域,因此我将其替换为 forEach 以便确定 info 的作用域和每次迭代中的 passLoc 变量。

这是使用 ES5 的 Array#map 的稍微精简的版本:

var async = require('async');

function run() {
    http.get(url, function(res) {
        if(res.statusCode === 200) {
            res.pipe(parse(function(err, data) {
                async.parallel(
                    // map data items to async tasks
                    data.slice(1).map(function(info) {
                        return function(cb) {
                            var passLoc = info[6].replace('block ', '').replace(/ /g, '+');
                            getLoc(passLoc, function(loc) {
                                cb(null, loc);
                            });
                        };
                    }),
                    function(err, locations) {
                        // consume data when all async tasks are finished
                        console.log(locations);
                    }
                );
            }));
        } else {
            console.error('The address is unavailable. (%d)', res.statusCode);
        }
    });
}

关于javascript - 可能的嵌套异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28794571/

相关文章:

javascript - ReactJS - 在不同组件中使用相同的钩子(Hook)

node.js - 无法要求node-wit

node.js - Mongoose 验证器

ruby - 在 Ruby 中解析文本文件和排序?

javascript - HTML5 表单验证无需提交

javascript - 按值降序对 json 进行排序

php - 提高 php-cli 中大型 csv 文件解析的性能

java - 从 URL 获取文件名

javascript - HTML 按钮重定向页面

javascript - 我可以让出子进程并在 Node.js 中返回响应吗?