2015-08-31 3 views
0

Я не эксперт по JavaScript (особенно с обещаниями и обратными вызовами), но то, что я в основном пытаюсь сделать, это сделать мой файл JavaScript синхронно выполнять следующие задачи: 1. Создать массив 2. Нажмите каждый элемент, который мне нужен, в массив 3. Отправьте массив контроллеру с вызовом post ajax. Вот функции, которые я использую:Заполнение массива перед отправкой с помощью 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

С быстрым взглядом, это выглядит, как вы 'post'ing для вашего действия контроллера до заполнения вашего объекта' listOfRestaurants' - это простой порядок выдачи операций? – wahwahwah

+0

Хм, где ваше обещание разрешилось? Служит ли служба google для вас? – Shilly

+0

Можете ли вы исправить фигурные скобки. В настоящий момент код несколько «странный» ... – Andreas

ответ

0

Добавить async: false в свой returnList обратный вызов, так как она позволяет другой запроса/операции произойдет только если этого запрос закончен.

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 принести/отправить данные только тогда, когда Defered являетсярешен, и не будет вызываться, если Отложенный объект либоразрешен, отклонен, или еще в процессе (Documentation).

0

Вы делаете первоначальный асинхронный вызов, чтобы получить места для местоположения, а когда это возвращается, вы делаете несколько асинхронных вызовов, чтобы получить детали для каждого места. Вам нужно подождать, пока все эти вызовы не вернутся, прежде чем вы сможете публиковать данные.

Вы можете сделать это, создав массив объектов JQuery Deferred, по одному для каждого вызова, чтобы получить детали для места. Затем вы можете использовать функцию $.when() для выполнения кода после того, как все эти объекты Отложенные объекты будут разрешены.

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

Смежные вопросы