Javascript 如何使用';请求';和';异步';
我正在编写一个测试代码,通过使用'request.js'和'async.js'从node.js上的Web API收集结果 这是我的示例代码Javascript 如何使用';请求';和';异步';,javascript,node.js,asynchronous,async.js,Javascript,Node.js,Asynchronous,Async.js,我正在编写一个测试代码,通过使用'request.js'和'async.js'从node.js上的Web API收集结果 这是我的示例代码 var request = require('request'); var async = require('async'); var addresses = [ "Tokyo", "Moscow", "Bagdhad", "Mountain View", "New York", ]; function acces
var request = require('request');
var async = require('async');
var addresses = [
"Tokyo",
"Moscow",
"Bagdhad",
"Mountain View",
"New York",
];
function accessUrl( address, callback ) {
options ={
headers: {'user-agent': 'Mozilla/5.0'},
url: 'http://api.openweathermap.org/data/2.5/weather?q=' + address,
json: true
};
request.get(options, function(err, response, body_json) {
if( !err && response.statusCode === 200 ){
return callback(address, body_json);
}
else{
console.log('error');
}
});
}
function showContent( address, body_json ) {
console.log( "%s : %s, %s (C)", address, body_json['weather'][0]['main'],
Math.round(body_json['main']['temp']-273.15));
return [ address, body_json['weather'][0]['main'],
Math.round(body_json['main']['temp']-273.15)];
}
var result = [];
async.map( addresses, function( item, callback ) {
result.push (accessUrl( item, showContent ));
}, function(err) {
});
console.log(result);
但结果是,
~$ node asyncsample1.js
[ undefined, undefined, undefined, undefined, undefined ]
Tokyo : Clear, 23 (C)
Mountain View : Mist, 10 (C)
Bagdhad : Clear, 10 (C)
New York : Clear, 22 (C)
Moscow : Clouds, 4 (C)
回调函数showContent()中的console.log()显示正确的结果,但收集的结果都是“未定义的”
如何在var result[]中获取结果?您正在将未定义的结果推送到这里,因为accessUrl是异步的。它返回undefined。在执行accessUrl回调之前,您不会有任何结果——但到那时,即使它返回一个结果,undefined已经被推送,结果也不会出现
// wrong
var result = [];
async.map( addresses, function( item, callback ) {
result.push (accessUrl( item, showContent ));
}, function(err) {
});
任何依赖于异步函数结果的逻辑都必须进入该函数的回调中。另外,async
为您处理输出数组,您只需将(err,result
传递给迭代器
//corrected
async.map( addresses
, function( item, callback ){
accessUrl( item, function(address, body_json){
result = showContent(address, body_json);
// tell async.map there was no error and this is the mapped result
callback(null, result);
});
}
, function(err, results) {
console.log(results)
});
如果我是你,我会做一些调整。首先处理出现请求错误的情况。其次,我喜欢在async中使用done
作为回调的名称,因为我通常发现我在另一个异步函数中使用async,而我通常已经有一个名为callback
的现有变量是父函数的回调。下面是我将如何做的:
//improved
function iterator(item, done){
accessUrl( item, function(err, address, body_json){
// you will have to tweak accessUrl to callback with three parameters instead of two
if(err){ return done(err) };
// the `return` is necessary, otherwise latter lines will still execute
result = showContent(address, body_json);
// tell async.map there was no error and this is the mapped result
done(null, result);
});
};
async.map( addresses
, iterator
, function(err, results) {
if(err){ console.log(err) };
console.log(results)'
});
另一种方法是,创建一个结果数组并逐个添加结果。这更接近您的原始想法,但由于async.map
自动构建结果数组,因此将此策略用于async.map没有意义
//alternative
function printWeather(callback){
var results = [];
async.forEachSeries(addresses
, function(item, done){
accessUrl( item, function(err, address, body_json){
if(err){ return done(err) };
result = showContent(address, body_json);
results.push(result);
done(null);
});
}
, function(err) {
if(err){ console.log(err) };
console.log(results);
//callback(err, results);
});
};
好的,让我向您介绍一下
async
的concat
函数。这是您修改过的程序
var request = require('request');
var async = require('async');
var addresses = [
"Tokyo",
"Moscow",
"Bagdhad",
"Mountain View",
"New York",
];
function accessUrl( address, callback ) {
options ={
headers: {'user-agent': 'Mozilla/5.0'},
url: 'http://api.openweathermap.org/data/2.5/weather?q=' + address,
json: true
};
request.get(options, function(err, response, body_json) {
if( !err && response.statusCode === 200 ){
return callback(null, [[ address, body_json['weather'][0]['main'],
Math.round(body_json['main']['temp']-273.15)]]);
}
else{
return callback(err);
}
});
}
async.concat (addresses, accessUrl, function(err, result) {
if (err) {
console.error(err);
} else {
console.log(result);
}
});
输出
[ [ 'Mountain View', 'Haze', 17 ],
[ 'Bagdhad', 'Clear', 18 ],
[ 'New York', 'Clear', 26 ],
[ 'Tokyo', 'Clouds', 22 ],
[ 'Moscow', 'Clouds', 3 ] ]
您不必自己同步结果。concat
会为您同步结果
如果您有兴趣了解async的concat是如何工作的,请尝试以下方法
让我确认一下,“result”是否只需要在async.map函数(err,results){}中处理?
async.map
函数接受地址数组并对每个项执行迭代器函数。每次调用迭代器函数时,它都会回调(err,result)
其中result是该地址的映射输出。async.map
的完成回调采用(err,results)
参数,其中results是映射输出,顺序与addresses数组相同。有关手动逐个添加结果的替代方法,请参阅我的最新编辑