2017-10-11 3 views
0

이 스크립트는 Google지도에서 지진 정보를 표시 할 수있는 웹 앱의 일부입니다. 이 스크립트는 Google지도를 비동기 적으로로드하고 Knockout ViewModel을 만듭니다. 사용자는 Knockout Observables (self.curFeedTypeself.curFeedTimeHorizon)와 연결된 일부 드롭 다운 메뉴를 통해 표시 할 지진을 선택할 수 있습니다. 그러면지도 뷰포트 경계에없는 지진 제목 목록이지도 옆에 표시됩니다. 지진 데이터는 USGS.gov의 AJAX 요청을 통해로드됩니다.Google지도의 바운더리로 필터링 된 geoJSON으로 녹아웃 뷰가 업데이트되지 않습니다.

피드 유형 업데이트 직후에 표시된 지진 제목 목록을 업데이트하고 싶습니다. 현재로서는 작동하지 않습니다. 이것은 비동기 문제라고 생각합니다. 디버거를 사용할 때 작동하지만 반대는 아닙니다.

지도 경계가 변경 될 때 UI를 업데이트하는 별도의 수신기가 있기 때문에 대부분의 기능이 작동하는 것으로 알고 있습니다. 그러나 지금은 지진 제목 목록이 피드가 변경되고지도가 이동 될 때까지 업데이트되지 않습니다.

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); 

답변

0

이 질문을 한 후에, 나는 대답을 알아 냈다.

다음 함수는 AJAX 요청을한다 :

이 기능을 암묵적으로 약속의 반환 값을 포장, 비동기 함수로 선언에도 불구하고
// 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; 
    } 

, 그 직전 빈 배열을 반환 기다리지 않고, AJAX 요청이 완료되기 전에. 따라서 약속은 즉시 완료되어 나머지 체인이 self.updateQuakeFeed()에서 실패하게됩니다.

구글의 다음 가이드 그림이 아웃 도움이되었다
async function getQuakeFeed() { 
    return $.getJSON(self.generateFeedUrl()); 
    } 

    self.populateQuakeModel = async function() { 
    let feedResults = await getQuakeFeed(); 
    let newQuakes = []; 
    feedResults.features.forEach(feature => { 
     newQuakes.push(new earthQuakeModel(feature)); 
    }); 
    return newQuakes; 
    } 

    self.updateQuakeFeed = async function() { 
    if (self.map) { 
     let newQuakes = await self.populateQuakeModel(); 
     self.loadedQuakes = newQuakes; 
     self.updateVisibleQuakes(self.map.getBounds()); 
    } 
    } 

: Promises "Compatibility with other libraries"이 설명하는이 진행하기 전에 충족되어야 위해

나는 즉시 약속의 AJAX 요청을 포장하고 대기하여이 문제를 수정 실제 ES6 Promise 객체에서 jQuery의 지연 --- the wrapper of return type from jQuery.ajax ---를 바로 래핑하는 값.