Ich entwickle eine Seite mit Leaflet, um eine Karte für eine Kunden-Website anzuzeigen. Die Seite lädt zuerst die Details der Karte - name, lat, long usw. basierend auf einer ID. Die Ladung erfolgt über Ajax zu einer sehr einfachen C# -Seite, die einen gespeicherten Prozess ausführt und das Recordset als JSON zurückgibt.jQuery Ajax Anruf funktioniert nur, wenn ich durch es gehe
Sobald die Karte geladen ist, gibt es einen zweiten Ajax-Aufruf, der Marker auf der Karte löscht und plottet. Dies ist eine ähnliche C# -Seite, die Fahrzeugdetails zurückgibt. Dieser Ajax-Aufruf wird dann in einen Aufruf setInterval (function()) gesetzt, um alle x Sekunden zu wiederholen.
Wenn ich die Seite normal laufe, wird nichts richtig geladen. Beim Durchsuchen des Debuggers in Firefox kann ich sehen, dass der erste Ajax-Aufruf undefiniert zurückgegeben wurde. Wenn ich einen Haltepunkt hinzufüge und durchschaue, was passiert, funktioniert es. Wenn ich den Haltepunkt entferne, schlägt es fehl.
Was mache ich hier falsch?
Haupt HTML-Datei
<head>
<meta http-equiv="x-ua-compatible" content="IE=11">
<meta charset="utf-8" />
<meta http-equiv="refresh" content="3600">
<title>Map Viewer</title>
<link rel="stylesheet" type="text/css" href="/Content/themes/base/all.css" />
<link rel="stylesheet" type="text/css" href="/Content/Site.css" />
<link rel="stylesheet" type="text/css" href="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css" />
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon.png">
<link rel="icon" type="image/png" href="/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="/favicon-16x16.png" sizes="16x16">
<script type="text/javascript" src="/Scripts/jquery-3.0.0.min.js"></script>
<script type="text/javascript" src="/Scripts/jquery-ui-1.11.4.min.js"></script>
<script type="text/javascript" src="http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js"></script>
<script type="text/javascript" src="/Scripts/leaflet-providers.js"></script>
<script type="text/javascript" src="/Scripts/leaflet-tracksymbol.js"></script>
<script type="text/javascript" src="/Scripts/leaflet-tracklayer.js"></script>
<script type="text/javascript" src="/Scripts/ctrack-clearybros.js"></script>
<meta name="viewport" content="width=device-width" />
</head>
<body >
<h1 id="pageTitle"></h1>
<div id="errorText"></div>
<div id="map"></div>
<script id="mapScript" type="text/javascript">
Script Block
var mapDetails;
var mapId = 1;
var reloadTime = 15 * 1000; //15 seconds
//var w = $(window).width();
//var h = $(window).height();
mapDetails = getMapDetails(mapId);
console.debug("Map details retrieved");
console.debug(mapDetails);
//$("#map").width(w);
//$("#map").height(h);
$("#pageTitle").text(mapDetails.mapTitle);
var map = new L.Map("map", {
center: mapDetails.mapCenter,
minZoom: 16,
maxZoom: 16,
zoom: 16,
reuseTiles: true,
unloadInvisibleTiles: true
});
console.debug("Map Created");
//console.debug(map);
var appId = "snip";
var appCode = "snip";
//using plugin
var tilesLayer = new L.tileLayer.provider("HERE.terrainDay", {
attribution: "Event Data © <a href=\"http://www.ctrackonline.com.au/\">Ctrack Australia</a> — Map Data © <a href=\"http://www.here.com\">HERE maps</a>",
app_id: appId,
app_code: appCode,
subdomains: '1234',
mapID: 'newest',
base: 'aerial',
maxZoom: 20,
type: 'maptile',
language: 'eng',
format: 'png8',
size: '256'
});
tilesLayer.addTo(map);
console.debug("tileLayer Created");
//console.debug(tilesLayer);
map.removeControl(map.zoomControl);
map.dragging.disable(); //disable map panning
map.doubleClickZoom.disable(); //disable click to recenter
map.touchZoom.disable();
map.scrollWheelZoom.disable();
map.boxZoom.disable();
map.keyboard.disable();
console.debug("Map options set");
var unitLayer = new L.FeatureGroup();
unitLayer.addTo(map);
populateUnitLayers(mapId) //prime the pump before the setInterval fires
console.debug("Vehicle layer populated");
console.debug(unitLayer);
//setInterval(function() {
// populateUnitLayers(mapId) //called every reloadTime seconds
//}, reloadTime);
</script>
<div id="ajaxLoadingHolder">
<div id="ajaxLoading"><img src="/Content/images/ajax-loader.gif" /></div>
</div>
Zusätzliche JS-Datei
function getMapDetails(mapId) {
var _mapTitle;
var _mapLatitude;
var _mapLongitude;
var _mapCenter;
var JsonUrl;
if (window.location.pathname == "/ClearyBros.cshtml") { JsonUrl = "/JSON/GetDetailForLocation"; }
if (window.location.pathname == "/CtrackMaps/ClearyBros.cshtml") { JsonUrl = "/CtrackMaps/JSON/GetDetailForLocation"; }
$.ajax({
method: "GET",
url: JsonUrl,
processData: true, //means data sent as querystring
dataType: "json", //,"text"
data: { mapId: mapId },
timeout: 60000
})
.done(function (results) {
if (jQuery.isEmptyObject(results)) {
console.error("Map details are blank");
}
else {
console.debug("Map details are not blank");
console.debug(results);
}
$.each(results, function (index, result) {
_mapTitle = result.Name;
_mapLatitude = result.Latitude;
_mapLongitude = result.Longitude;
_mapCenter = new L.LatLng(_mapLatitude, _mapLongitude);
});
})
.fail(function (xhr, status, error) {
console.error("Failed to load map details");
if (status == "timeout") {
var errorText = "Timeout reached loading map details.";
displayError(errorText);
}
else {
var errortext = "Error state \"" + status + "\" occured loading map details. \n" + error;
displayError(errorText);
}
});
var obj = {
mapTitle: _mapTitle,
mapLatitude: _mapLatitude,
mapLongitude: _mapLongitude,
mapCenter: _mapCenter
};
return obj;
}
function populateUnitLayers(mapId) {
// set all our marker default values here. This doesnt get added to a layer.
var trackSymbolDefault = new L.trackSymbol(new L.LatLng(0.0, 0.0), {
trackId: 0,
fill: true,
fillColor: '#ffffff',
fillOpacity: 1.0,
stroke: true,
color: '#000000',
opacity: 1.0,
weight: 1.0,
speed: 0,
course: 0,
heading: 0,
leaderTime: 0
});
var JsonUrl;
if (window.location.pathname == "/ClearyBros.cshtml") { JsonUrl = "/JSON/GetUnitsForLocation"; }
if (window.location.pathname == "/CtrackMaps/ClearyBros.cshtml") { JsonUrl = "/CtrackMaps/JSON/GetUnitsForLocation"; }
unitLayer.clearLayers();
//unit0Layer.clearLayers();
//unit1Layer.clearLayers();
//unit2Layer.clearLayers();
$("#error-text").hide();
$.ajax({
method: "GET",
url: JsonUrl,
processData: true, //means data sent as querystring
dataType: "json", //"text",
data: { mapId: mapId },
timeout: 60000
})
.done(function (results) {
$.each(results, function (index, result) {
var marker = createUnitMarker(result, trackSymbolDefault);
if (marker.options.speed == 0) {
marker.options.color = '#cccccc';
//marker.addTo(unit0Layer);
//unit0Layer.addTrack(marker);
}
else if (marker.options.speed > 60) {
marker.options.color = '#ff0000';
//marker.addTo(unit1Layer);
//unit1Layer.addTrack(marker);
}
else {
marker.options.color = '#ffff00';
//marker.addTo(unit2Layer);
//unit2Layer.addTrack(marker);
}
//marker.addTo(map);
marker.addTo(unitLayer);
});
})
.fail(function (xhr, status, error) {
console.error("Failed to load vehicle details");
displayError("Error getting data while loading vehicle positions");
if (status == "timeout") {
//alert("Timeout reached.");
displayError("Timeout reached loading map details");
}
else {
//alert("Error state \"" + status + "\" occured loading vehicle positions. \n" + error);
var errorText = "Error state \"" + status + "\" occured loading vehicle positions.";
displayError(errorText);
}
});
}
function createUnitMarker(result, defaults) {
var _marker;
const kphToMph = 0.621371;
var _latlng = new L.LatLng(result.Latitude, result.Longitude);
var _track = result.NodeId;
var _speed = result.Speed * kphToMph; // Km/h to m/h
var _course = result.Heading * Math.PI/180.0; // Radians from north
var _heading = result.Heading * Math.PI/180.0;
_marker = new L.trackSymbol(_latlng, {
trackId: _track,
fill: defaults.options.fill,
fillColor: defaults.options.fillColor,
fillOpacity: defaults.options.fillOpacity,
stroke: defaults.options.stroke,
color: defaults.options.color,
opacity: defaults.options.opacity,
weight: defaults.options.weight,
speed: _speed,
course: _course,
heading: _heading,
leaderTime: defaults.options.leaderTime
});
var _note = "<p><b>Unit Name:</b> " + result.UnitName + "<br /><b>Unit Desc:</b> " + result.UnitDesc + "<br /><b>Last Updated:</b> " + result.AssembledTime + "<br /><b>Speed:</b> " + result.Speed + " km/h</p>"
_marker.bindPopup(_note);
console.debug("TrackId " + _marker.options.trackId + " added");
return _marker;
}
function displayError(message) {
$("#error-text").text(message);
$("#error-text").show();
}
$(document).ajaxStart(function() {
$("#ajaxLoading").show();
}).ajaxStop(function() {
$("#ajaxLoading").hide();
});
Mögliches Duplikat von [Wie gebe ich die Antwort von einem asynchronen Anruf zurück?] (Http://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous- call) – Andreas
Wenn Sie beim Durchlaufen ein unterschiedliches Verhalten bemerken, ist dies oft das Ergebnis von asynchronen Anforderungen, die in einer anderen Reihenfolge verarbeitet werden. Die Lösung verspricht oft, wie von @Andreas oben erwähnt. – smoksnes
Mein Verständnis ist, dass die Verwendung von jQuery und den .done() - und .fail() - Ereignissen dieses aschetische Warteproblem vermeidet. Ihr Code wird erst ausgelöst, wenn er geantwortet hat. $ Schnipsel ({ // Optionen }) .done (function (Ergebnisse) {}) .fail (function (XHR, Status, Fehler) {}) – Hecatonchires