【问题标题】:node - how does async.map work?节点 - async.map 是如何工作的?
【发布时间】:2018-05-04 19:23:43
【问题描述】:

在阅读了async 之后,我认为下面的代码会将 http/API 调用返回的所有值的总和输出到控制台;但它似乎在第一个 http 调用返回后立即触发,并且只显示一个等于从 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();

【问题讨论】:

    标签: node.js async.js


    【解决方案1】:

    传递给迭代对象 (httpGet) 的callback 使用不正确。第一个参数 (price) 被视为错误。来自the docs

    如果iteratee 将错误传递给其回调,则主callback(用于映射函数)会立即调用错误。

    所以

    callback(price);
    

    应该是

    callback(null, price);
    

    所以async 在第一次迭代后不会停止。

    【讨论】:

      【解决方案2】:

      我相信这里有两个不同的问题:

      1. 您可能知道,我们不能像在同步代码中那样在异步代码中使用return 语句,这就是我们使用回调的原因。节点样式回调的形式为function (err, result) {},其中第一个参数是错误(如果有),第二个参数是函数的结果(返回值)。根据docsAsync.map(coll, iteratee, callback) 将停止执行,如果 iteratee 将错误传递给它的回调。

        当您的iteratee-函数调用它的回调函数时:callback(price),您实际上是在停止执行,因为价格是作为error 参数传递的。要“返回”price 变量,您想要做的是这样调用回调:callback(null, price)

      2. 通常,map-functions 用于

        对列表的每个元素应用[ying] 给定函数,以相同的顺序返回结果列表。

        异步库的 map 函数做同样的事情,IE:遍历一个数组并返回一个结果项的数组,就像法线贴图(下面)方法一样。

        [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 函数,或者简单地将作为结果返回的值求和。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-01-23
        • 1970-01-01
        • 1970-01-01
        • 2020-05-29
        • 1970-01-01
        • 2015-03-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多