【问题标题】:Add async result to array in nodejs将异步结果添加到nodejs中的数组
【发布时间】:2016-10-24 18:30:40
【问题描述】:

我对 Node.js 还很陌生,从它的生命周期来看,我似乎无法弄清楚整个回调异步的事情。

我想要实现的是“相对”简单,如果这一切都在阻塞调用。

1) 请求列表

2) 遍历元素

3) 为新列表创建新元素,新元素属性是另一个请求的结果

4) 将新元素添加到新列表中

细节:

var originalList = [{
    provider: "ABC",
    loc: [13.37224, 52.53862],
    state: 22
}, {
    provider: "CDE",
    loc: [13.37124, 52.53262],
    state: 33
}, {
    provider: "EFG",
    loc: [13.37214, 52.53662],
    state: 44
}];

var newElement;
var newList = [];
var vLat, vLng;

originalList.forEach(function(element, index, array) {

    newElement = {
        provider: element.provider,
        state: element.state
    };
    vLat = element.loc[1];
    vLng = element.loc[0];

    async.parallel([
        function(callback) {
            var location;
            googleMapsClient.reverseGeocode({
                latlng: [vLat, vLng],
                result_type: ['street_address'],
                location_type: ['ROOFTOP', 'APPROXIMATE']
            }, function(err, response) {
                if (!err) {
                    var result = response.json.results;
                    location = result[0].formatted_address;
                    newElement.location = location;
                    callback();
                } else {
                    callback(err);
                }
            });
        }
    ], function(err) {
        if (err) console.log(err);
        newList.push(newElement);
    });
});

我省略了第二个异步函数,它也发出谷歌地图请求,并且应该将该结果也添加到 newElement。

我真的很困惑为什么 newElement 没有获得新属性 (newElement.location)。我知道这将是基本的。

【问题讨论】:

  • json array 好像是错误的,数组中每个对象后面都有一个额外的}
  • 你的意思是 originalList 数组?只是奇怪的格式
  • 使用async.map(),你可以将迭代器中的东西传递给最终回调

标签: javascript node.js asynchronous


【解决方案1】:

循环也需要异步来控制处理所有项目的流程。使用 async.each() 或 async.eachSeries() (依次处理列表):

var originalList = [{
    provider: "ABC",
    loc: [13.37224, 52.53862],
    state: 22
}, {
    provider: "CDE",
    loc: [13.37124, 52.53262],
    state: 33
}, {
    provider: "EFG",
    loc: [13.37214, 52.53662],
    state: 44
}];

var newList = [];

async.each(originalList, function (element, eachCb) {

    var newElement = {
        provider: element.provider,
        state: element.state
    };
    var vLat = element.loc[1];
    var vLng = element.loc[0];

    async.parallel([
        function(callback) {
            var location;
            googleMapsClient.reverseGeocode({
                latlng: [vLat, vLng],
                result_type: ['street_address'],
                location_type: ['ROOFTOP', 'APPROXIMATE']
            }, function(err, response) {
                if (!err) {
                    var result = response.json.results;
                    location = result[0].formatted_address;
                    newElement.location = location;
                    callback();
                } else {
                    callback(err);
                }
            });
        }
    ], function(err) {
        if (err) {
            console.log(err);
        } else {
            newList.push(newElement);
        }
        eachCb();   // <<<<< call to signal it's done!!
    });
}, function (err) {
    console.log('finish processing all items in originalList');
});

如果只有 1 个任务,则不需要 async.parallel()

【讨论】:

    【解决方案2】:

    我认为您的代码应该如下所示

    var originalList = [{
        provider: "ABC",
        loc: [13.37224, 52.53862],
        state: 22
    }, {
        provider: "CDE",
        loc: [13.37124, 52.53262],
        state: 33
    }, {
        provider: "EFG",
        loc: [13.37214, 52.53662],
        state: 44
    }];
    
    var newElement;
    var newList = [];
    var vLat, vLng;
    
    originalList.forEach(function(element, index, array) {
    
        newElement = {
            provider: element.provider,
            state: element.state
        };
        vLat = element.loc[1];
        vLng = element.loc[0];
    
        async.parallel([
            function(callback) {
                var location;
                googleMapsClient.reverseGeocode({
                    latlng: [vLat, vLng],
                    result_type: ['street_address'],
                    location_type: ['ROOFTOP', 'APPROXIMATE']
                }, function(err, response) {
                    if (!err) {
                        var result = response.json.results;
                        location = result[0].formatted_address;
                        newElement.location = location;
                        callback(null, 'success');
                    } else {
                        callback(err);
                    }
                });
            }
        ], function(err, results) {
            if (err) console.log(err);
            newList.push(newElement);
        });
    });
    

    按照 async.parallel API 文档,if (!err) 中的 callback() 必须是 callback(err, results)

    【讨论】:

      猜你喜欢
      • 2015-08-18
      • 1970-01-01
      • 2019-08-08
      • 2018-11-13
      • 1970-01-01
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      • 2011-11-30
      相关资源
      最近更新 更多