我不是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调用发送。 我将不胜感激任何帮助或建议。
答案 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);
});
}
});