需要帮助创建带回调的异步函数

时间:2015-07-22 14:25:09

标签: javascript angularjs node.js socket.io

我有一个JSON对象,其中一些条目(约会)每个都是“位置ID”。然后我循环通过这些条目并通过socketIO向我的nodeJS服务器发出请求,以从位置id的文档中获取数据。

最后我需要一个带有lat / lng数据的数组来在地图上创建一些标记。

以下是代码:

//controller for showing map
.controller('MapCtrl', function($scope, socket){

    socket.emit('getApp', staticUserid);

        socket.on('getApps', function (appdata) {
                var locArr = [];
                for (var i = 0; i < appdata.length; i++) {
                    if (appdata[i].locationid != '') {
                        locArr.push(appdata[i].locationid);
                    }
                }
                var LatLngArr = [];
                for (var j = 0; j < locArr.length; j++) {
                    socket.emit('getLocation', locArr[j]);
                    socket.on('getLoc', function (locData) {
                        console.log('received lat/lng: ' + locData.lat + '/' + locData.lng);
                        if (!LatLngArr[j]) LatLngArr[j] = []
                        LatLngArr[j][0] = locData.lat;
                        LatLngArr[j][1] = locData.lng;
                    });
                }
                //console.log('test:'+LatLngArr[0][0]);
        });

    var newMarkers = [[52.549678, 13.3879516],[52.5442992, 13.352809],[52.5186283,13.3761181]]; // this should be the generated array
    var newCenter = [52.549678, 13.3879516];
    createMap(newCenter,newMarkers);

})

问题是,var LatLngArr没有在......

之外定义
socket.on('getLoc', function (locData)

如果有人可以帮助我,那将是非常好的: - )

非常感谢!

3 个答案:

答案 0 :(得分:1)

如果你可以使用Promises

.controller('MapCtrl', function($scope, socket){

    socket.emit('getApp', staticUserid);

    socket.on('getApps', function (appdata) {
        var locArr = [];
        for (var i = 0; i < appdata.length; i++) {
            if (appdata[i].locationid != '') {
                locArr.push(appdata[i].locationid);
            }
        }
        var LatLngArr = [];
        var promises = [];
        for (var j = 0; j < locArr.length; j++) {
            promises[j] = (function(captured_j) {
                return new Promise(function(resolve, reject) {
                    socket.emit('getLocation', locArr[captured_j]);
                    socket.on('getLoc', function (locData) {
                        console.log('received lat/lng: ' + locData.lat + '/' + locData.lng);
                        if (!LatLngArr[captured_j]) LatLngArr[captured_j] = []
                        LatLngArr[captured_j][0] = locData.lat;
                        LatLngArr[captured_j][1] = locData.lng;
                        resolve({index: captured_j, result: LatLngArr[captured_j]});
                    });
                });
            }(j));
        }
        Promise.all(promises).then(function(arr) {
            // ******************************************
            // ******************************************
            // arr is an array of {index: #, result [lat, lng]} - but you can also use LatLngArr
            // ******************************************
            // ******************************************
        });
    });
    var newMarkers = [[52.549678, 13.3879516],[52.5442992, 13.352809],[52.5186283,13.3761181]]; // this should be the generated array
    var newCenter = [52.549678, 13.3879516];
    createMap(newCenter,newMarkers);
})

答案 1 :(得分:0)

试试这个

for (var j = 0; j < locArr.length; j++) {
    (function(captured_j) {
        socket.emit('getLocation', locArr[captured_j]);
        socket.on('getLoc', function (locData) {
            console.log('received lat/lng: ' + locData.lat + '/' + locData.lng);
            if (!LatLngArr[captured_j]) LatLngArr[captured_j] = []
            LatLngArr[captured_j][0] = locData.lat;
            LatLngArr[captured_j][1] = locData.lng;
            //
            // the required result
            //
            if (j === 0) {
                console.log('test:'+LatLngArr[0][0]);
            }
            //
        });
    }(j));
}

答案 2 :(得分:0)

您的代码失败的原因是由于该行的异步性质:

socket.on('getLoc', function (locData)

因此,当您注册回调时,实际上会定义LatLngArr,但在回调被调用时它不再存在。原因是JavaScript使用Closures

您可以查看此主题:How do JavaScript closures work?

因此你必须将它包装在IIFE中。这样,函数立即执行,使j的值按预期运行,因为它不再引用外部范围的j

编辑:一个非常好的解释可以在David Hermann&#34;有效Javascript&#34;的第13项中找到。 - 我完全可以推荐的一本书。如果您在理解它时遇到问题,请查看此thread可能有所帮助。