节点 - async.map 是如何工作的?
node - how does async.map work?
阅读 async
后,我假设下面的代码会将 http/API 调用返回的所有值的总和输出到控制台;但它似乎在第一次 http 调用 returns 后立即触发,并且只显示 'total' 值等于从 API.
返回的第一个值
我对 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();
传递给迭代器 (httpGet
) 的 callback
使用不正确。第一个参数 (price
) 被认为是一个错误。来自 the docs:
If iteratee
passes an error to its callback, the main callback
(for the map function) is immediately called with the error.
所以
callback(price);
应该是
callback(null, price);
因此 async
在第一次迭代后不会停止。
我认为这里有两个不同的问题:
如您所知,我们不能像在同步代码中那样在异步代码中使用 return
语句,这就是我们改用回调的原因。节点式回调采用 function (err, result) {}
形式,其中第一个参数是错误(如果有),第二个参数是函数的结果(return 值)。根据 docs,
Async.map(coll, iteratee, callback)
将停止执行,如果
iteratee
将错误传递给它的回调。
由于您的 iteratee
-函数正在调用其回调:callback(price)
,您实际上是在停止执行,因为价格作为 error
参数传递。您想对 "return" price
变量做的是这样调用回调:callback(null, price)
通常,map-函数用于
appl[ying] a given function to each element of a list, returning a list of results in the same order.
async 库的 map 函数做同样的事情,IE:遍历一个数组,returns 一个结果项的数组,就像法线贴图(下面)方法所做的那样。
[1, 2, 3].map(function (nbr) { return nbr*2 }) // returns [2, 4, 6]
您的 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
});
为了求和这些值,我建议使用 reduce 函数,或者简单地将 return 的值求和作为结果。
阅读 async
后,我假设下面的代码会将 http/API 调用返回的所有值的总和输出到控制台;但它似乎在第一次 http 调用 returns 后立即触发,并且只显示 'total' 值等于从 API.
我对 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();
httpGet
) 的 callback
使用不正确。第一个参数 (price
) 被认为是一个错误。来自 the docs:
If
iteratee
passes an error to its callback, the maincallback
(for the map function) is immediately called with the error.
所以
callback(price);
应该是
callback(null, price);
因此 async
在第一次迭代后不会停止。
我认为这里有两个不同的问题:
如您所知,我们不能像在同步代码中那样在异步代码中使用
return
语句,这就是我们改用回调的原因。节点式回调采用function (err, result) {}
形式,其中第一个参数是错误(如果有),第二个参数是函数的结果(return 值)。根据 docs,Async.map(coll, iteratee, callback)
将停止执行,如果iteratee
将错误传递给它的回调。由于您的
iteratee
-函数正在调用其回调:callback(price)
,您实际上是在停止执行,因为价格作为error
参数传递。您想对 "return"price
变量做的是这样调用回调:callback(null, price)
通常,map-函数用于
appl[ying] a given function to each element of a list, returning a list of results in the same order.
async 库的 map 函数做同样的事情,IE:遍历一个数组,returns 一个结果项的数组,就像法线贴图(下面)方法所做的那样。
[1, 2, 3].map(function (nbr) { return nbr*2 }) // returns [2, 4, 6]
您的
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 });
为了求和这些值,我建议使用 reduce 函数,或者简单地将 return 的值求和作为结果。