Ce script fait partie d'une application Web qui permet aux utilisateurs d'afficher des informations sur les séismes sur une carte Google Map. Le script charge les google maps de manière asynchrone et crée un Knockout ViewModel. L'utilisateur peut choisir quels tremblements de terre afficher via certains menus déroulants, qui sont liés à Knockout Observables (self.curFeedType
et self.curFeedTimeHorizon
). L'application affichera alors une liste de titres de tremblement de terre à côté de la carte, filtrant ceux qui ne sont pas dans les limites de la fenêtre de la carte. Les données sismiques sont chargées via une requête AJAX de USGS.gov. Je souhaite que la liste des titres de tremblement de terre affichés se mette à jour immédiatement après la mise à jour des types de flux --- cela ne fonctionne pas actuellement. Je crois que c'est un problème asynchrone --- quand j'utilise le débogueur cela fonctionne, mais pas vice versa.La vue Knockout ne se met pas à jour avec geoJSON Filtré par des limites de Google Map
Je sais que la plupart des fonctionnalités fonctionnent car il existe un programme d'écoute distinct qui met à jour l'interface utilisateur lorsque les limites de la carte changent. À l'heure actuelle, toutefois, la liste des titres de tremblement de terre ne sera pas mise à jour avant que le flux ne soit modifié et que la carte ne soit déplacée.
function ControlViewModel() {
var self = this;
self.map = null;
self.loadedQuakes = [];
self.visibleQuakes = ko.observableArray();
// types of available earthquake feeds from USGS.gov
self.feedTypes = ["significant", "4.5", "2.5", "1.0", "all"];
self.feedTimeHorizons = ["hour", "day", "week", "month"];
// use significant and week as default feed when app loads
self.curFeedType = ko.observable("significant");
self.curFeedTimeHorizon = ko.observable("week");
function setVisibleQuakes (bounds, quakesToFilter) {
self.visibleQuakes(quakesToFilter.filter(quake => {
return bounds.contains(quake.latLon);
}));
}
self.updateVisibleQuakes = function(bounds, loadedQuakes) {
loadedQuakes ? setVisibleQuakes(bounds, loadedQuakes) :
setVisibleQuakes(bounds, self.loadedQuakes);
}
// Generate a url for the desired earthquake feed
self.generateFeedUrl = function() {
let baseFeedUrl = `https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/${self.curFeedType()}_${self.curFeedTimeHorizon()}.geojson`;
return baseFeedUrl;
}
// load quakes from USGS and create new model objects
async function getQuakeFeed() {
let loadedQuakes = [];
$.getJSON(self.generateFeedUrl(), function(data) {
for (var i = 0; i < data.features.length; i++) {
loadedQuakes.push(new earthQuakeModel(data.features[i]));
};
});
return loadedQuakes;
}
self.updateQuakeFeed = async function() {
if (self.map) {
let loadedQuakes = getQuakeFeed();
loadedQuakes.then(result => {
self.updateVisibleQuakes(self.map.getBounds(), result);
self.loadedQuakes = result;
});
}
}
// update the feed when either select menu changes
self.curFeedType.subscribe(self.updateQuakeFeed, null);
self.curFeedTimeHorizon.subscribe(self.updateQuakeFeed, null);
// call for inital setup
self.updateQuakeFeed();
}
var controlViewModel = new ControlViewModel();
// create a new Google Map
function initMap() {
let map = new google.maps.Map(document.getElementById('map_container'), {
center: {lat: 0, lng: 0},
zoom: 3
});
console.log(map);
controlViewModel.map = map;
// listener to let UI know that map bounds have changed
map.addListener('idle', function() {
let bounds = map.getBounds();
controlViewModel.updateVisibleQuakes(bounds, null);
});
}
ko.applyBindings(controlViewModel);