【问题标题】:Google Maps API Javascript Error谷歌地图 API Javascript 错误
【发布时间】:2018-02-20 05:34:12
【问题描述】:

所以,我正在构建一个网络应用程序,它使用谷歌地图的 API 来显示一个带有一些标记的地图,每次你点击一个标记,它应该显示来自该位置的 5 篇文章,这些文章由谷歌新闻提供,问题是,我对 javascript 和 web 开发还很陌生,我已经尝试了好几个小时来自己解决这个问题,但我不知道如何解决。我将保留我的 JS 文件和我的使用 flask 处理服务器请求的 python 文件,但我确信服务器端没有任何问题。

js:

// Google Map
var map;

// markers for map
var markers = [];

// info window
var info = new google.maps.InfoWindow();

// execute when the DOM is fully loaded
$(function() {

    // styles for map
    // https://developers.google.com/maps/documentation/javascript/styling
    var styles = [

        // hide Google's labels
        {
            featureType: "all",
            elementType: "labels",
            stylers: [
                {visibility: "off"}
            ]
        },

        // hide roads
        {
            featureType: "road",
            elementType: "geometry",
            stylers: [
                {visibility: "off"}
            ]
        }

    ];

    // options for map
    // https://developers.google.com/maps/documentation/javascript/reference#MapOptions
    var options = {
        center: {lat: 42.3770, lng: -71.1256}, // Cambridge, MA
        disableDefaultUI: true,
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        maxZoom: 14,
        panControl: true,
        styles: styles,
        zoom: 13,
        zoomControl: true
    };

    // get DOM node in which map will be instantiated
    var canvas = $("#map-canvas").get(0);

    // instantiate map
    map = new google.maps.Map(canvas, options);

    // configure UI once Google Map is idle (i.e., loaded)
    google.maps.event.addListenerOnce(map, "idle", configure);

});

/**
 * Adds marker for place to map.
 */
function addMarker(place)
{
    // initialize marker
    var marker = new google.maps.Marker({
        position: {lat: place.latitude, lng: place.longitude},
        map: map,
        title: place.place_name + ', ' + place.admin_name1,
        icon: "http://maps.google.com/mapfiles/kml/pal2/icon31.png"
    });

    // add marker with its place to markers array
    markers.push({marker, place});

    index = markers.length - 1

    // add event listener to the marker
    google.maps.event.addListener(markers[index].marker, 'click', showArticles(markers[index]))
}

/**
 * Gets the articles to be displayed
 */
function showArticles(local)
{
    var parameters = {
        geo: local.place.place_name
    };

    // get articles for the place
    json = $.getJSON(Flask.url_for("articles"), parameters);

    // store those articles in a string containing html
    html = "<ul>"

    json.done(function (){

        if(json.responseJSON){
            for (var i = 0; i < json.responseJSON.length; i++){
            html += "<li><a src=\"" + json.responseJSON[i].link + "\">" + json.responseJSON[i].title + "</a></li>";
            }

            html += "</ul>"

            console.log(json.responseJSON)
            console.log(html)

            showInfo(local.marker, html)

        }}).fail(function (){
            showInfo(local.marker, "")
        })

}

/**
 * Configures application.
 */
function configure()
{
    // update UI after map has been dragged
    google.maps.event.addListener(map, "dragend", function() {

        // if info window isn't open
        // http://stackoverflow.com/a/12410385
        if (!info.getMap || !info.getMap())
        {
            update();
        }
    });

    // update UI after zoom level changes
    google.maps.event.addListener(map, "zoom_changed", function() {
        update();
    });

    // configure typeahead
    $("#q").typeahead({
        highlight: false,
        minLength: 1
    },
    {
        display: function(suggestion) { return null; },
        limit: 10,
        source: search,
        templates: {
            suggestion: Handlebars.compile(
                "<div>" +
                "{{place_name}}, {{admin_name1}}, {{postal_code}}" +
                "</div>"
            )
        }
    });

    // re-center map after place is selected from drop-down
    $("#q").on("typeahead:selected", function(eventObject, suggestion, name) {

        // set map's center
        map.setCenter({lat: parseFloat(suggestion.latitude), lng: parseFloat(suggestion.longitude)});

        // update UI
        update();
    });

    // hide info window when text box has focus
    $("#q").focus(function(eventData) {
        info.close();
    });

    // re-enable ctrl- and right-clicking (and thus Inspect Element) on Google Map
    // https://chrome.google.com/webstore/detail/allow-right-click/hompjdfbfmmmgflfjdlnkohcplmboaeo?hl=en
    document.addEventListener("contextmenu", function(event) {
        event.returnValue = true;
        event.stopPropagation && event.stopPropagation();
        event.cancelBubble && event.cancelBubble();
    }, true);

    // update UI
    update();

    // give focus to text box
    $("#q").focus();
}

/**
 * Removes markers from map.
 */
function removeMarkers()
{
    for(var i = 0; i < markers.length; i++){
        markers[i].marker.setMap(null)
    }

    markers = []
}

/**
 * Searches database for typeahead's suggestions.
 */
function search(query, syncResults, asyncResults)
{
    // get places matching query (asynchronously)
    var parameters = {
        q: query
    };
    $.getJSON(Flask.url_for("search"), parameters)
    .done(function(data, textStatus, jqXHR) {

        // call typeahead's callback with search results (i.e., places)
        asyncResults(data);
    })
    .fail(function(jqXHR, textStatus, errorThrown) {

        // log error to browser's console
        console.log(errorThrown.toString());

        // call typeahead's callback with no results
        asyncResults([]);
    });
}

/**
 * Shows info window at marker with content.
 */
function showInfo(marker, content)
{
    // start div
    var div = "<div id='info'>";
    if (typeof(content) == "undefined")
    {
        // http://www.ajaxload.info/
        div += "<img alt='loading' src='/static/ajax-loader.gif'/>";
    }
    else
    {
        div += content
    }

    // end div
    div += "</div>";

    // set info window's content
    info.setContent(div);

    // open info window (if not already open)
    info.open(map, marker);
}

/**
 * Updates UI's markers.
 */
function update()
{
    // get map's bounds
    var bounds = map.getBounds();
    var ne = bounds.getNorthEast();
    var sw = bounds.getSouthWest();

    // get places within bounds (asynchronously)
    var parameters = {
        ne: ne.lat() + "," + ne.lng(),
        q: $("#q").val(),
        sw: sw.lat() + "," + sw.lng()
    };
    $.getJSON(Flask.url_for("update"), parameters)
    .done(function(data, textStatus, jqXHR) {

       // remove old markers from map
       removeMarkers();

       // add new markers to map
       for (var i = 0; i < data.length; i++)
       {
           addMarker(data[i]);
       }
    })
    .fail(function(jqXHR, textStatus, errorThrown) {

        // log error to browser's console
        console.log(errorThrown.toString());
    });

};

Python:

import os
import re
from flask import Flask, jsonify, render_template, request, url_for
from flask_jsglue import JSGlue

from cs50 import SQL
from helpers import lookup

# configure application
app = Flask(__name__)
JSGlue(app)

# ensure responses aren't cached
if app.config["DEBUG"]:
    @app.after_request
    def after_request(response):
        response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
        response.headers["Expires"] = 0
        response.headers["Pragma"] = "no-cache"
        return response

# configure CS50 Library to use SQLite database
db = SQL("sqlite:///mashup.db")

@app.route("/")
def index():
    """Render map."""
    if not os.environ.get("API_KEY"):
        raise RuntimeError("API_KEY not set")
    return render_template("index.html", key=os.environ.get("API_KEY"))

@app.route("/articles")
def articles():
    """Look up articles for geo."""

    # get geo
    geo = request.args.get("geo")

    # if there is no geo, return error
    if geo == '' or geo == None:
        raise RuntimeError("missing geo")

    # get articles for this geo
    articles = lookup(geo)

    if len(articles) > 5:
        articles = articles[:5]

    # return them as a json object
    return jsonify(articles)

@app.route("/search")
def search():
    """Search for places that match query."""

    place = request.args.get("q") + "%"

    # get everything that mathes this query
    places = db.execute("SELECT * FROM places WHERE postal_code LIKE :place OR place_name LIKE :place OR admin_name1 LIKE :place LIMIT 10", place=place)

    # return them as objects
    return jsonify(places)

@app.route("/update")
def update():
    """Find up to 10 places within view."""

    # ensure parameters are present
    if not request.args.get("sw"):
        raise RuntimeError("missing sw")
    if not request.args.get("ne"):
        raise RuntimeError("missing ne")

    # ensure parameters are in lat,lng format
    if not re.search("^-?\d+(?:\.\d+)?,-?\d+(?:\.\d+)?$", request.args.get("sw")):
        raise RuntimeError("invalid sw")
    if not re.search("^-?\d+(?:\.\d+)?,-?\d+(?:\.\d+)?$", request.args.get("ne")):
        raise RuntimeError("invalid ne")

    # explode southwest corner into two variables
    (sw_lat, sw_lng) = [float(s) for s in request.args.get("sw").split(",")]

    # explode northeast corner into two variables
    (ne_lat, ne_lng) = [float(s) for s in request.args.get("ne").split(",")]

    # find 10 cities within view, pseudorandomly chosen if more within view
    if (sw_lng <= ne_lng):

        # doesn't cross the antimeridian
        rows = db.execute("""SELECT * FROM places
            WHERE :sw_lat <= latitude AND latitude <= :ne_lat AND (:sw_lng <= longitude AND longitude <= :ne_lng)
            GROUP BY country_code, place_name, admin_code1
            ORDER BY RANDOM()
            LIMIT 10""",
            sw_lat=sw_lat, ne_lat=ne_lat, sw_lng=sw_lng, ne_lng=ne_lng)

    else:

        # crosses the antimeridian
        rows = db.execute("""SELECT * FROM places
            WHERE :sw_lat <= latitude AND latitude <= :ne_lat AND (:sw_lng <= longitude OR longitude <= :ne_lng)
            GROUP BY country_code, place_name, admin_code1
            ORDER BY RANDOM()
            LIMIT 10""",
            sw_lat=sw_lat, ne_lat=ne_lat, sw_lng=sw_lng, ne_lng=ne_lng)

    # output places as JSON
    return jsonify(rows)

这是我在运行页面时出现在控制台上的错误,如果需要,我可以留下一个指向运行应用程序的服务器的链接。 enter image description here

【问题讨论】:

  • 错误信息和代码的图片不是很有用。请在您的问题中提供错误的完整文本(可能对标题也有帮助),以及产生该错误的minimal reproducible example
  • 对不起,这是唯一出现的错误,如果我尝试从代码中删除任何内容,我会以某种方式破坏应用程序。这是应用程序的链接,它目前正在运行,也许你可以在控制台ide50-lucalopes.cs50.io 中找到一些东西,再说一次,我对编程很陌生,做了一个多月,网络编程只是一个多星期了,很抱歉我无法提供更多信息。
  • @geocodezip 请向我询问更具体的内容,我很乐意为您提供。

标签: javascript python google-maps google-maps-api-3


【解决方案1】:

以下代码在第 93 行返回一个未定义的值:

// get articles for the place
json = $.getJSON(Flask.url_for("articles"), parameters);

当您尝试访问 json.responseJSON 时,错误发生在第 100 行。您使用的条件将需要更像以下之一:

if ( typeof json != "undefined" )

if ( json.responseJSON.length > 0 )

【讨论】:

  • 如果有一个值,我只尝试对返回的值做一些事情,有一个 if 条件来检查它。此外,这部分代码应该获取特定地点的文章,而我收到了这些文章。
  • 在第 100 行,检查 json var 是否未定义: if ( typeof json != "undefined" )
  • 刚刚试过,没有改变任何东西,我之前遇到过 json.responseJSON 错误,因为它是未定义的,当我添加该条件时它解决了该问题,这是另一回事
  • 如果你从错误图片来看,我的javascript文件叫做scripts.js,出现的都不是我的,都是来自google maps的API。
猜你喜欢
  • 2016-05-09
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-24
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多