将状态传递给javascript中的子功能?

时间:2013-11-05 02:38:01

标签: javascript

我有一套方向,我试图用不同的颜色渲染。我要求Google发出指示,但我不确定如何存储状态,以便在返回路由结果时,我可以使用正确的颜色呈现每个状态。

所以,作为一个例子,我有这个对象:

{routes: [{start_lat : 0.0, start_lng : 0.0, end_lat : 1.0, end_lng : 1.0, color : "#ff0000"},
          {start_lat : 1.0, start_lng : 1.0, end_lat : 2.0, end_lng : 2.0, color : "#00ff00"}]}

这是我的功能:

directionsService = new google.maps.DirectionsService();
for(var i = 0; i < routes.length; i++){
    var dir_request = {
        origin : new google.maps.LatLng(routes[i]['start_lat'], routes[i]['stop_lng']),
        destination : new google.maps.LatLng(routes[i]['end_lat'], routes[i]['end_lng']),
        travelMode : google.maps.TravelMode.WALKING
    };
    directionsService.route(dir_request, function(result, status) {
        if(status == google.maps.DirectionsStatus.OK){
            // render with custom logic depending on which route this is here
        }
    })
}

如何将状态(例如,for循环中的索引)附加到每个请求,以便可以从结果处理函数访问它?

3 个答案:

答案 0 :(得分:1)

您需要使用closure scoped variables来执行此操作。当您尝试在路由回调函数中使用i时,您正在使用一个名为闭包的概念,其中可以从内部函数访问在父函数中声明的变量。

但是使用closures in a loop有自己的问题,因为闭包变量的相同实例将在循环内创建的所有内部函数之间共享,因此当调用内部函数时,您将获得分配给的最后一个值循环中的变量。

这里的解决方案是在循环内创建一个局部闭包,如下所示

directionsService = new google.maps.DirectionsService();
for (var i = 0; i < routes.length; i++) {
    (function (idx) {
        var dir_request = {
            origin: new google.maps.LatLng(routes[idx]['start_lat'], routes[idx]['stop_lng']),
            destination: new google.maps.LatLng(routes[idx]['end_lat'], routes[idx]['end_lng']),
            travelMode: google.maps.TravelMode.WALKING
        };
        directionsService.route(dir_request, function (result, status) {
            // the variable idx will refer to the array index for the current iteration
            if (status == google.maps.DirectionsStatus.OK) {
                // render with custom logic depending on which route this is here
            }
        })
    })(i)
}

答案 1 :(得分:1)

一些答案​​已经描述了如何通过显式闭包来解决问题。这是使用Function.prototype.bind的另一个例子。

directionsService.route(dir_request, (function(result, status) {
    //the this keyword now refers to the correct route object
    console.log(this);

    if(status == google.maps.DirectionsStatus.OK){
        // render with custom logic depending on which route this is here
    }
}).bind(routes[i]));

修改

这是一种有效的另一种方法,可以在没有bind的情况下完成。在循环中内联作用域安全函数效率不高,因为必须在每次迭代时创建一个新函数。 最好为此目的创建一个函数并重用它。

function createRouteCallback(route) {
    return function (result, status) {
        if(status == google.maps.DirectionsStatus.OK) {
            // render with custom logic depending on which route this is here

            //you can just use route here
            console.log(route);
        }
    };
}

然后在循环中你可以做到:

directionsService.route(dir_request, createRouteCallback(routes[i]));

答案 2 :(得分:0)

马克是对的。除非发生奇怪的事情,否则所有函数的变量都在回调function(result,status)中可用。有关说明和一些示例,请参阅here。由于您在创建回调时知道dir_request,因此可以直接在回调代码中引用它。如果您需要访问i数组,您还应该可以参考routes

如果您在获取值时遇到任何问题,可以尝试添加一个间接层:

function makeCallback(dir_request) {
    return function(result,status) {
        //your code, and you can refer to dir_request
    };
}

然后致电

directionsService.route(dir_request, makeCallback(dir_request));

我必须在Greasemonkey脚本中执行一次,以确保在创建function()时锁定了我需要的变量。