2016-10-07 6 views
0

座標をAngularJSサービスに保存する必要があるWebアプリケーションをプログラミングしています。私はIonic Framework、JavaScript、HTMLを使用しています。配列が配列要素として「未定義」を返すのはなぜですか?

私の問題は、配列自体が正しく表示されていることです。単一の要素が「未定義」として出力されることです。私のコードサンプルで

//Controller für die Map und ihre Funktionen 
mapApp.controller('MapCtrl', function($scope, $ionicLoading, dataService) { 

//Funktion zur Geocodierung von Adressen Eingabe String 
var geocodeAddress = function(geocoder, resultsMap) { 

    //Hole Textfeld Input aus Service 
    var address = dataService.getAddress(); 
    //Geocode Funktion analog zu Google Maps API Beispiel 
    geocoder.geocode({'address' : address}, function(results, status) { 
    if (status === google.maps.GeocoderStatus.OK) { 
     resultsMap.setCenter(results[0].geometry.location); 
     resultsMap.setZoom(14); 

     dataService.setLatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng()); 

     var marker = new google.maps.Marker({ 
     map: resultsMap, 
     position: results[0].geometry.location, 
     }); 
     //onClick Info Fenster mit Adresse 
     var infoString = "Dein Startpunkt: <br>" + results[0].formatted_address; 
     var infoWindow = new google.maps.InfoWindow({ 
     content: infoString 
     }); 
     marker.addListener("click", function() { 
     infoWindow.open(resultsMap, marker); 
     }); 
    } 
    else { 
     alert("Ups, da ist etwas schief gegangen ! Error: " + status); 
    } 
    }); 
} 

//Funktion zur Initialisierung der Map 
//inklusive Geocoding und Erreichbarkeitspolygonen 
var initialize = function() { 
     //Route360° stuff 
     r360.config.serviceKey = 'KADLJY0DAVQUDEZMYYIM'; 
     r360.config.serviceUrl = 'https://service.route360.net/germany/'; 

     var myLatlng = new google.maps.LatLng(48.383, 10.883); 
     var mapOptions = { 
     center: myLatlng, 
     zoom: 8, 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
     }; 
     var map = new google.maps.Map(document.getElementById("map"), mapOptions); 

     var geocoder = new google.maps.Geocoder(); 
     var p = new Promise(function (resolve, reject) { 

     geocodeAddress(geocoder, map); 

     if(dataService.getLatLng()) { 
      resolve("Success!"); 
     } 
     else { 
      reject("Failure!"); 
     } 
     }); 
     //console.log(dataService.getLatLng()); 
     p.then(function() { 
     //console.log(dataService.getLatLng()); 
     var coords = dataService.getLatLng(); 
     console.log(coords); 
     console.log(coords[0]); 
     console.log(JSON.stringify(coords, null, 4)); 

     var time = dataService.getTime(); 
     var move = dataService.getMove(); 
     var colorPolygonLayer = new GoogleMapsPolygonLayer(map); 
     showPolygons(48.4010822, 9.987607600000047, colorPolygonLayer, time, move); 
     }); 
     $scope.map = map; 
} 
ionic.Platform.ready(initialize); 
}); 

//Funtkion zum Erstellen und Anzeigen der Erreichbarkeitspolygone 
var showPolygons = function(lat, lng, polygonLayer, time, move) { 
    //Setzen der Optionen für die Berechnung der Polygone 
    var travelOptions = r360.travelOptions(); 

    //Lat-Lng bestimmen 
    travelOptions.addSource({ lat : lat, lng : lng }); 

    //Zeitintervalle bestimmen 
    travelOptions.setTravelTimes(time*60); 

    //Fortbewegungsmittel bestimmen 
    travelOptions.setTravelType(move); 

    r360.PolygonService.getTravelTimePolygons(travelOptions, function(polygons) { 
     polygonLayer.update(polygons); 
    }); 
} 

//Controller für die Daten 
//Eigentlich nur Daten in Service schreiben onClick 
mapApp.controller("DataCtrl", function($scope, dataService) { 
    $scope.setData = function() { 
    var address = document.getElementById("address").value; 
    var time = document.getElementById("time").value; 
    var move = $scope.move; 
    dataService.setData(address,time,move); 
    }; 
}); 

//Service um Daten zwischen Controllern zu benutzen 
mapApp.service("dataService", function() { 
    var address; 
    var time; 
    var move; 
    var latlng = []; 

    //Adresse, Zeit und Fortbewegungsmittel setzen 
    this.setData = function(passed_address, passed_time, passed_move) { 
    address = passed_address; 
    time = passed_time; 
    move = passed_move 
    }; 
    this.setLatLng = function (lat, lng) { 
    latlng.push(lat); 
    latlng.push(lng); 
    }; 
    //Getter 
    this.getAddress = function() { 
    return address; 
    }; 
    this.getTime = function() { 
    return time; 
    }; 
    this.getMove = function() { 
    return move; 
    }; 
    this.getLatLng = function(){ 
    return latlng; 
    } 
}) 

特定の行が!(http://imgur.com/a/u33hg

それらは私の戻り値

console.log(coords); 
console.log(coords[0]); 
console.log(JSON.stringify(coords, null, 4)); 

されています。私が言ったように、console.log(coords)は正しい配列を出力しますが、console.log(coords [0])を呼び出す場合は、 "undefined"を返します(console.log(JSON.stringify

誰かが私にその問題を説明することができますか、それとももっと良い解決策を私に与えることができますか?

編集@Jasonカストの提案後:

var arr = []; 
     var p = new Promise(function (resolve, reject) { 
     geocodeAddress(geocoder, map); 
     asyncPush(arr, dataService.getLatLng(), resolve); 
     }); 

     p.then(function() { 
     var a = getArr(); 
     console.log(a); 
     console.log(a[0]); 

     var time = dataService.getTime(); 
     var move = dataService.getMove(); 
     var colorPolygonLayer = new GoogleMapsPolygonLayer(map); 
     showPolygons(48.4010822, 9.987607600000047, colorPolygonLayer, time, move); 
     }); 
     function asyncPush(a, val, cb) { 
     setTimeout(function() { 
      a.push(val); 
      cb(); 
     } , 0); 
     } 
     function getArr() {return arr; } 

そして、これが結果です! http://imgur.com/a/A5hAJ

私は、彼らが再び未定義だったので、座標ごとのasyncPushを使用することができなかったので、私はちょうどそれが配列の配列であり、動作しているようですので、今全体編曲: ArrayにVARを追加しました。もちろん、3次元配列を2次元のものに保存するための回避策を構築することはできますが、それはあなたが意図したものでしたか?

編集は:2次元の一つに3次元の配列を保存しようとすると、未定義の変数を返し、再び

ソリューション編集:は、だから私は最終的に約束については、このチュートリアルに従って、私の問題を解決することができます:http://exploringjs.com/es6/ch_promises.html

トリックはを初期化する約束でgeocodeAddress機能をラップし、私のに約束を.then関数を呼び出すことでした2つの関数を互いに呼び出させる関数です。私に大きな頭痛の種を与えた

とにかく
var geocodeAddress = function(geocoder, resultsMap) { 
    return new Promise(function(resolve, reject) { 
    //Hole Textfeld Input aus Service 
    var address = dataService.getAddress(); 
    //Geocode Funktion analog zu Google Maps API Beispiel 
    geocoder.geocode({'address' : address}, function(results, status) { 
     if (status === google.maps.GeocoderStatus.OK) { 
     resultsMap.setCenter(results[0].geometry.location); 
     resultsMap.setZoom(14); 

     dataService.setLatLng(results[0].geometry.location.lat(), results[0].geometry.location.lng()); 

     var marker = new google.maps.Marker({ 
      map: resultsMap, 
      position: results[0].geometry.location, 
     }); 
     //onClick Info Fenster mit Adresse 
     var infoString = "Dein Startpunkt: <br>" + results[0].formatted_address; 
     var infoWindow = new google.maps.InfoWindow({ 
      content: infoString 
     }); 
     marker.addListener("click", function() { 
      infoWindow.open(resultsMap, marker); 
     }); 
     } 
     if(dataService.getLatLng()) { 
     resolve("Success"); 
     } 
     else { 
     alert("Ups, da ist etwas schief gegangen ! Error: " + status); 
     reject("Failed"); 
     } 
    }); 
    }); 
} 

//Funktion zur Initialisierung der Map 
//inklusive Geocoding und Erreichbarkeitspolygonen 
var initialize = function() { 
     //Route360° stuff 
     r360.config.serviceKey = 'KADLJY0DAVQUDEZMYYIM'; 
     r360.config.serviceUrl = 'https://service.route360.net/germany/'; 

     var myLatlng = new google.maps.LatLng(48.383, 10.883); 
     var mapOptions = { 
     center: myLatlng, 
     zoom: 8, 
     mapTypeId: google.maps.MapTypeId.ROADMAP 
     }; 
     var map = new google.maps.Map(document.getElementById("map"), mapOptions); 
     var geocoder = new google.maps.Geocoder(); 

     geocodeAddress(geocoder, map) 
     .then(function() { 
     var coords = dataService.getLatLng(); 
     var time = dataService.getTime(); 
     var move = dataService.getMove(); 
     var colorPolygonLayer = new GoogleMapsPolygonLayer(map); 
     showPolygons(coords[0], coords[1], colorPolygonLayer, time, move); 
     }); 
     $scope.map = map; 
} 
ionic.Platform.ready(initialize); 
}); 

、多くのJSの知識がなくても、このためのソリューションを探して、あなたの助けのために非常に多くの@Jasonカストをありがとう:ここに私のコードです。

多くの点、 ジュリアン

+0

あなたがにconsole.log 'の出力を投稿することができます(コード); – Hackerman

+0

[] 0:52.520006599999991:13.404953999999975長さ:2__proto__:配列[0] controlle rs.js:68 undefined フォーマットが正しくありません。申し訳ありません。これは2つの座標の出力例です。 –

+0

これは 'console.log(coords);'の出力です。確かですか?ちょうどそれが必要です。 – Hackerman

答えて

2

これは、プログラムの非同期性質とconsole.log自体の原因です。約束pインサイド

は、それがプロセスは、それが空の配列の形でない値を返すdataService.getLatLng()のチェック(、これまでに引き続きそう完了したときにチェックされることはありません非同期機能geocodeAddressの呼び出しです真実である)、resolveが実行され、最後にconsole.log行のファンクションブロックに入ります。これによりconsole.logの非同期動作とconsole.log(coords)が最終的にそれが値を出力する機会を有するSTDOUTに印刷する場合dataService.getLatLngから返された配列の値を使用しての基準に

。しかし、console.log(coords[0])が即値を取得するので、それはundefinedであり、後で再びSTDOUTに出力されます。その操作は同期であるため、同じことがJSON出力にも適用されます。

基本的にコードが今何をするか: 続行する前に必ず非同期待機をするためにチェック

var arr = []; 
 

 
var p = new Promise(function(resolve, reject) { 
 
    asyncPush(arr, 'foo'); 
 
    
 
    if (getArr()) { 
 
    resolve(); 
 
    } 
 
}); 
 

 
p.then(function() { 
 
    var a = getArr(); 
 
    
 
    console.log(a); 
 
    console.log(a[0]); 
 
    console.log(JSON.stringify(a, null, 2)); 
 
}); 
 

 
function asyncPush(a, val) { 
 
    setTimeout(function() { a.push(val) }, 0); 
 
} 
 
    
 
function getArr() { return arr; }

var arr = []; 
 

 
var p = new Promise(function(resolve, reject) { 
 
    asyncPush(arr, 'foo', resolve); 
 
}); 
 

 
p.then(function() { 
 
    var a = getArr(); 
 
    
 
    console.log(a); 
 
    console.log(a[0]); 
 
    console.log(JSON.stringify(a, null, 2)); 
 
}); 
 

 
function asyncPush(a, val, cb) { 
 
    setTimeout(function() { a.push(val); cb(); }, 0); 
 
} 
 
    
 
function getArr() { return arr; }

+0

あなたの答えをありがとう!関数asyncPush(a、val、cb)の使用についてさらに説明できますか?なぜ私はそれが何をするのか、なぜそれが私の問題を助けてくれるのか理解できません。 –

+0

@JuleWolf 'asyncPush'は、両方とも非同期呼び出しを使用する点で、' geocodeAddress'と同等です。非同期操作がいつ完了したかを知るためのメカニズムを提供することにより( 'cb'引数を介して)、それを呼び出すコードはいつ操作を継続するかを知るでしょう。 –

+0

ありがとうございます。私はできるだけ早くそれを試し、あなたの解決策の結果を投稿します。 –