在使用ajax

时间:2015-08-31 15:22:34

标签: javascript jquery arrays ajax

我不是JavaScript的专家(特别是承诺和回调),但我基本上要做的是让我的JavaScript文件同步执行以下任务: 1.创建一个数组 2.将我需要的每个元素推入数组中 3.使用post ajax调用将阵列发送到控制器。 以下是我正在使用的功能:

function initialize() {
    var detroit = new google.maps.LatLng(42.331427, -83.0457538);
    map = new google.maps.Map(document.getElementById('map'), {
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        center: detroit,
        zoom: 15
    });
    var request = {
        location: detroit,
        radius: 500,
        types: ['restaurant']
    };
    infowindow = new google.maps.InfoWindow();
    service = new google.maps.places.PlacesService(map);
    var promise = new Promise(function (resolve, reject) {
        service.search(request, callback);
    });
    promise.then(returnList);
}

function callback(results, status) {
    if (status === google.maps.places.PlacesServiceStatus.OK) {
        for (var i = 0; i < results.length; i++) {
            restaurantCount = results.length;
            createMarker(results[i]);
        }
    }

    function createMarker(place) {
        var placeLoc = place.geometry.location;
        var marker = new google.maps.Marker({
            map: map,
            position: place.geometry.location
        });
        var request = {
            reference: place.reference
        };
        service.getDetails(request, function (details, status) {
            foodPlace = {
                PlaceID: details.place_id,
                Name: details.name,
                PriceLevel: details.price_level,
                WebSite: details.website,
                Rating: details.rating,
                AddressNumber: details.formatted_address,
                PhoneNumber: details.formatted_phone_number,
            };
            listOfRestaurants.push(foodPlace);
            //ajaxHelper('/api/Restaurants/', 'POST', foodPlace);
            google.maps.event.addListener(marker, 'click', function () {
                infowindow.setContent(details.name + "<br />" + details.formatted_address + "<br />" + details.website + "<br />" + details.rating + "<br />" + details.formatted_phone_number + "<br />" + details.price_level);
                infowindow.open(map, marker);
            });
        });
    }

    function returnList() {
        if (restaurantCount == listOfRestaurants.length) {
            $.ajax({
                url: '/Home/Index',
                data: listOfRestaurants,
                type: 'POST',
                traditional: true,
                success: alert("yay")
            }).fail(alert("oops"));
        }
    }

我正在进行POST调用的控制器是

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Index(List<Restaurant> restaurants)
{
    List<Restaurant> validRestaurants = new List<Restaurant>();

    foreach(Restaurant r in restaurants)
    {
        if (ModelState.IsValid)
        {
            validRestaurants.Add(r);
        }

    }

    return View(validRestaurants);
}
}

在我的代码中我有

google.maps.event.addDomListener(window, 'load', initialize); 

在窗口加载完成后开始初始化函数。

我遇到的问题是,在列表有任何数据之前,数据总是通过ajax调用发送。 我将不胜感激任何帮助或建议。

2 个答案:

答案 0 :(得分:0)

async: false回调中添加returnList,因为允许其他请求/操作仅在此请求结束时才会发生。< / p>

function returnList() {
    if (restaurantCount == listOfRestaurants.length) {
        $.ajax({
            url: '/Home/Index',
            async: false,
            data: listOfRestaurants,
            type: 'POST',
            traditional: true,
            success: alert("yay")
        }).fail(alert("oops"));
    }
}

注意: 据我所知,您应该在done()对象上使用then()代替promise,因为您希望returnList函数仅在Deferred 已解析时获取/发送数据,并且如果Deferred对象为则不会被调用 已解决,拒绝或仍在进行中Documentation)。

答案 1 :(得分:0)

您正在进行初始异步调用以获取某个位置的位置,当它返回时,您正在进行多次异步调用以获取每个位置的详细信息。您需要等到所有这些调用都返回后再发布数据。

您可以通过创建一个JQuery Deferred对象数组来完成此操作,每个调用一个用于获取某个地点的详细信息。然后,您可以使用$.when()函数在解析所有这些Deferred对象后执行代码。

jQuery(function($) {
    var detroit = new google.maps.LatLng(42.331427, -83.0457538);

    var map = new google.maps.Map($('#map')[0], {
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        center: detroit,
        zoom: 15
    });

    var infowindow = new google.maps.InfoWindow();
    var service = new google.maps.places.PlacesService(map);

    var request = {
        location: detroit,
        radius: 500,
        types: ['restaurant']
    };

    // Make the request to get the places for the location.
    service.search(request, function(places, status) {
        if (status === google.maps.places.PlacesServiceStatus.OK) {
            // For each place returned for the location, make a request to get
            // the details. An array of JQuery Deferred objects is created for
            // the requests.
            var deferreds = $.map(places, function(place) {
                return getDeferredFoodPlace(place);
            });

            // The "done" callback will be executed when all the Deferred
            // objects are resolved, that is, when all the requests for
            // details have returned.
            $.when.apply($, deferreds).done(function() {
                // Use "$.makeArray()" to convert the arguments to the
                // "done" callback to an array, and then use "$.map()"
                // to weed out the nulls.
                var foodPlaces = $.map($.makeArray(arguments), function(foodPlace) {
                    return foodPlace;
                });

                // Create the markers for the food places that were
                // successfully returned.
                $.each(foodPlaces, function(i, foodPlace) {
                     createMarker(foodPlace);
                });

                // This is where the food places that were successfully
                // returned can be posted to the server.
            });
        }
    });

    // This function creates a JQuery Deferred object that is resolved
    // when the service.getDetails() call returns. that is, when its
    // callback function is called.
    function getDeferredFoodPlace(place) {
        return $.Deferred(function(deferred) {
            service.getDetails({
                reference: place.reference
            }, function(details, status) {
                if (status === google.maps.places.PlacesServiceStatus.OK) {
                    deferred.resolve({
                        Location: place.geometry.location,
                        PlaceID: details.place_id,
                        Name: details.name,
                        PriceLevel: details.price_level,
                        WebSite: details.website,
                        Rating: details.rating,
                        AddressNumber: details.formatted_address,
                        PhoneNumber: details.formatted_phone_number
                    });
                } else {
                    // If the call to get the details fails, this code
                    // will still resolve the Deferred object, but with
                    // a null value. Notice that null values are ignored
                    // in the "done" callback for the "$.when()" call.
                    // This means the places for which the details could
                    // not be obtained will simply be ignored with no
                    // error message.
                    // Alternatively, we could call ".reject()" instead
                    // of ".resolve()". That would cause the "fail"
                    // callback for the "$.when()" call to be executed.
                    // An error message could then be displayed, but
                    // it would mean everything fails if one fails.
                    deferred.resolve(null);
                }
            });
        });
    }

    // This functions creates a marker on the map for the given food place.
    function createMarker(foodPlace) {
        var marker = new google.maps.Marker({
            map: map,
            position: foodPlace.Location
        });
        google.maps.event.addListener(marker, 'click', function() {
            infowindow.setContent(foodPlace.Name + "<br />"
                + foodPlace.AddressNumber + "<br />"
                + foodPlace.WebSite + "<br />"
                + foodPlace.Rating + "<br />"
                + foodPlace.PhoneNumber + "<br />"
                + foodPlace.PriceLevel);
            infowindow.open(map, marker);
        });
    }
});

jsfiddle