[英]node - how does async.map work?
After reading about async
, I assumed the code below would output to the console the total of all values returned from the http/API call; 在阅读了有关
async
,我假设下面的代码会将从http / API调用返回的所有值的总和输出到控制台。 but it seems to fire immediately after the first http call returns, and only shows a 'total' value equal to the first value returned from the API. 但它似乎在第一个http调用返回后立即触发,并且仅显示等于从API返回的第一个值的“总计”值。
Where is my misunderstanding about how async.map works? 我对async.map的工作方式有何误解?
var http = require('https');
const
async = require('async');
var MongoClient = require('mongodb').MongoClient;
var dbUrl = "mongodb://localhost:27017/";
var total = 0;
var tokens = [ {
name : "tron"
}, {
name : 'cardano'
}, {
name : 'nucleus-vision'
}, {
name : 'ripple'
}, {
name : 'litecoin'
}, {
name : 'havven'
}];
function run() {
doStuff();
setInterval(doStuff, 1 * 60 * 1000);
};
function doStuff() {
total = 0;
async.map(tokens, httpGet, function (value){
console.log('async done ', total);
});
}
function httpGet(token, callback) {
var url = 'https://api.coinmarketcap.com/v1/ticker/' + token.name;
http.get( url,
function(res) {
var body = '';
res.on('data', function(chunk) {
body += chunk;
});
res.on('end', function() {
var jsonObj = JSON.parse(body);
var price = parseFloat(jsonObj[0].price);
total += price;
MongoClient.connect(dbUrl, function(err, db) {
if (err)
throw err;
var dbo = db.db("crypto");
dbo.collection("tick").insertOne(jsonObj[0],
function(err, res) {
if (err)
throw err;
db.close();
});
});
callback(price);
});
}).on('error', function(e) {
console.log("Got an error: ", e);
});
};
run();
callback
that is passed to an iteratee ( httpGet
) is used incorrectly. 传递给iteratee(
httpGet
)的callback
使用不正确。 The first argument ( price
) is considered an error. 第一个参数(
price
)被认为是错误。 From the docs : 从文档 :
If
iteratee
passes an error to its callback, the maincallback
(for the map function) is immediately called with the error.如果
iteratee
将错误传递给其回调,则立即使用错误调用主callback
(用于map函数)。
So 所以
callback(price);
should rather be 应该是
callback(null, price);
So async
does not halt after the first iteration. 因此,
async
不会在第一次迭代后停止。
I believe there are two separate problems here: 我相信这里有两个独立的问题:
As you may know, we cannot use return
statements in asynchronous code like we would in synchronous code, which is why we use callbacks instead. 您可能知道,我们不能像异步代码那样在异步代码中使用
return
语句,这就是为什么我们使用回调的原因。 Node-style callbacks are on the form function (err, result) {}
, where the first parameter is the error (if any) and the second the result of the function (the return value). 节点样式的回调在表单
function (err, result) {}
,其中第一个参数是错误(如果有),第二个参数是函数的结果(返回值)。 According to the docs , Async.map(coll, iteratee, callback)
will stop the execution if the iteratee
passes an error to its callback. 根据文档 ,如果
iteratee
将错误传递给其回调,则Async.map(coll, iteratee, callback)
将停止执行。
As your iteratee
-function is calling its callback as such: callback(price)
, you're effectively stopping execution, as price is passed as the error
parameter. 当您的
iteratee
像这样调用其回调: callback(price)
,由于price作为error
参数传递了,您实际上正在停止执行。 What you want to do to "return" the price
variable, is to call the callback as so: callback(null, price)
要“返回”
price
变量,您要做的是这样调用回调: callback(null, price)
Typically, map -functions are used for 通常,将map函数用于
appl[ying] a given function to each element of a list, returning a list of results in the same order.
将给定函数应用于列表的每个元素,以相同顺序返回结果列表。
The map function of the async library does the same, IE: iterates through an array and returns an array of the resulting items, just like the normal map (below) method does. 异步库的map函数也做同样的事情,即IE:遍历一个数组并返回结果项的数组,就像普通的map方法(下面)一样。
[1, 2, 3].map(function (nbr) { return nbr*2 }) // returns [2, 4, 6]
The result parameter of your callback
(IE, the third parameter to async.map) will be called with an array of prices, and not the summed value of the prices. callback
的结果参数(IE,async.map的第三个参数)将使用价格数组而不是价格的总和来调用。
async.map(tokens, httpGet, function (error, total) { console.log(error); // prints undefined (unless there was an error) console.log(total); // prints an array of prices });
For summing the values, I would recommend the reduce function, or simply sum the values returned as a result. 为了对这些值求和,我建议使用reduce函数,或者简单地对作为结果返回的值求和。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.