对异步循环使用递归:如何访问推送数组数据?

时间:2016-04-14 15:16:18

标签: javascript node.js asynchronous callback

这个想法是多次运行地理编码(对阵数组)。为了循环异步函数,我决定使用递归方式。

var geocoder = require('geocoder')
var geocoded = []

//Example array
var result = [{
  'company_no': 'A',
  'address': 'a'
}, {
  'company_no ': 'B',
  'address': 'b'
}]

function geocodeOneAsync(result, callback) {
  var n = result.length

  function tryNextGeocode(i) {
    if(i >= n) {
      //onfailure("alldownloadfailed")
      return
    }
    var address = result[i].address
    geocoder.geocode(address, function (err, data) {

      geocoded.push(result[i].company_no)
      console.log('data1' + JSON.stringify(
          geocoded)) //Result is ==> data1["A"], data1["B"]
      tryNextGeocode(i + 1)

      //  }
    })
  }
  console.log('data1' + JSON.stringify(geocoded))
  tryNextGeocode(0)
}
geocodeOneAsync(result, function () {
  JSON.stringify('data final ' + geocoded) // result is  empty []. I want to access the final geocoded array?

})

基本上问题是如何获得最终价值。

2 个答案:

答案 0 :(得分:1)

为此,最简单的方法是使用map和Promise而不是递归。

function geocodeOneAsync(result, callback) {
    // with map you get an array of promises
    var promises = result.map(function (company) {
        return new Promise(function (resolve, reject) {
            var address = company.address;
            geocoder.geocode(address, function (err, data) {
                if(err) {
                    reject(err);
                }
                resolve(company.company_no);
            });
        }).catch(function(error) {
            // you can handle error here if you don't want the first occuring error to abort the operation.
        });
    });

    // then you resolve the promises passing the array of result to the callback.
    Promise.all(promises).then(callback);
}

geocodeOneAsync(result, function (geocodedArray) {
    // here geocoded is ['A','B']
    JSON.stringify(geocodedArray);
});

作为额外奖励,所有异步操作都是并行完成的。

答案 1 :(得分:0)

如果这不能回答您的问题,我道歉。我相信你需要在递归终止条件中调用你的回调:

files = dir('*.dat');
for k = 1:numel(files)
    fid = fopen(files(k).name, 'rt');

    %// Do stuff
    fclose(fid);
end

完整代码(我自己修改过):

if ( i >= n ) {
    callback();
}

我得到的输出是:

var geocoder = require('geocoder');
var geocoded = [];

function geocodeOneAsync(result, callback) {
    var n = result.length;
    function tryNextGeocode(ii) {
        if (ii >= n ) {
            //onfailure("alldownloadfailed")
            callback();
            return;
        }

        var address = result[ii].address
        geocoder.geocode(address, function (err, data) {
            geocoded.push(result[ii].company_no);
            console.log('data1' + JSON.stringify(geocoded)); //Result is ==> data1["A"], data1["B"]_++
            console.log("n=" +n + ",ii=" + ii);
            tryNextGeocode(ii + 1);
        });
    }
    console.log('data1' + JSON.stringify(geocoded));
    tryNextGeocode(0);
};

//Example array
var result = [
    {'company_no': 'A,','address': 'a'},
    {'company_no': 'B', 'address': 'b'}
];
geocodeOneAsync(result, function () {
     console.log(JSON.stringify('data final ' + geocoded)); // result is  empty []. I want to access the final geocoded array?
});

希望有所帮助!