可能的嵌套异步函数
possible nested asynchronous function
所以我在这里阅读了很多关于异步函数的不同答案,但我想我想多了我的问题,或者我一直盯着它看太久了,但我想不通。因此,非常感谢您的帮助。
所以我正在解析一个 csv 文件,然后尝试通过另一个 api 获取 lat/long。但我无法访问函数之外的 lat/lng 。下面是我的代码,我已尽我所能对其进行评论,如果有任何问题或更好的方法,请告诉我。
谢谢,
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 -- 您正在同步尝试在任何异步操作完成之前访问结果 (location
)。
由于您有多个并行的异步操作 运行,您可以使用 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);
}
});
}
所以我在这里阅读了很多关于异步函数的不同答案,但我想我想多了我的问题,或者我一直盯着它看太久了,但我想不通。因此,非常感谢您的帮助。
所以我正在解析一个 csv 文件,然后尝试通过另一个 api 获取 lat/long。但我无法访问函数之外的 lat/lng 。下面是我的代码,我已尽我所能对其进行评论,如果有任何问题或更好的方法,请告诉我。
谢谢,
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 -- 您正在同步尝试在任何异步操作完成之前访问结果 (location
)。
由于您有多个并行的异步操作 运行,您可以使用 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);
}
});
}