2013-11-05 74 views
0

我有一組方向,我試圖用不同的顏色呈現。我請求谷歌的指示,但我不知道如何存儲狀態,以便當路由結果返回時,我可以渲染每個適當的顏色。將狀態傳遞給JavaScript中的子函數?

所以,作爲一個例子,我有這樣的對象:

{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循環)到每個請求,以便它可以從結果處理函數中訪問?

+0

這就是所謂的閉包,我覺得 – Markasoftware

回答

1

您需要利用closurescoped 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) 
} 
+0

謝謝,這非常有幫助。 – Catherine

0

馬爾卡是對的。除非發生奇怪的事情,否則函數的所有變量都可在回調function(result,status)內使用。有關說明和一些示例,請參閱here。由於您在創建回調時知道dir_request,因此可以直接在回調代碼中引用它。如果您需要訪問routes陣列,您還應該能夠參考i

如果您有跨所獲得的價值有任何問題,你可以嘗試添加了一個間接層:

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()時我需要的變量被鎖定。

+0

但是如果我通過循環我的數組,不會我在不同的指數從響應返回時我請求的路線索引?事實上,Arun P. Johny所描述的究竟是什麼。 – Catherine

+0

@凱瑟琳不,這個答案中提出的解決方案實際上比Arun P. Jhonny建議的解決方案要好,它只是沒有很好的解釋,並沒有關閉正確的變量。查看我的答案編輯。 – plalx

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])); 
+0

是的,我想過有一個單獨的功能,但我也想知道如何才能做到這一點。謝謝! – Catherine