Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何使用';请求';和';异步';_Javascript_Node.js_Asynchronous_Async.js - Fatal编程技术网

Javascript 如何使用';请求';和';异步';

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

我正在编写一个测试代码,通过使用'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 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数组相同。有关手动逐个添加结果的替代方法,请参阅我的最新编辑