2010-11-08 3 views
0

ok У меня есть вызов ajax, который возвращает объект json.jquery приостанавливает цикл до тех пор, пока не будет выполнено глобальное условие

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

Я хочу Переберите и затем выполнить дополнительный вызов ajax (который будет геокодировать данные), а затем выполнить другой вызов ajax для сохранения в базе данных.

проблема в моем цикле for все работает слишком быстро, и между вызовами и сбоями браузера нет паузы, или функция сохранения в базу данных добавляет неверные данные.

$('#geo_batch').click(function(){ 
      var ajax_load = "<label><img src='/images/icons/loadinfo.gif' alt='saving location...' /> Loading data...</label>"; 
      $("#batch_detail").html(ajax_load); 
      $('#batch_buttons').hide(); 
      saveall = true; 
      var form = $("form"); //Grab the form element from the DOM 
      //alert(form.serialize()); 
      var mydata = form.serialize(); 
      $.ajax({ 
       type: "POST", 
       url: 'geo_getupdate_list.php', 
       data: mydata, 
       dataType: 'json', 
       success: function(dat) { 
        processbatch(dat);// process the returned data 
       }, 
       error: function(dat) { //Triggered if an error communicating with server 
        //alert('fail'); 
        $("#batch_detail").html('<label>There was an error: '+dat+'<label>'); 
        $('#batch_buttons').show(); 
       } 
      }); 
      return false; //Ignore the default behavior of the button click 
     }); 

функция данных процесса

function processbatch(dat){ 
      // Cache the batch_detail element 
      $("#batch_detail").html('<label>Locations have been retrieved:<br>' + dat + '<label>'); 
      $('#batch_buttons').show(); 
      var count = dat.location.length - 1; 
      for(i=0; i < count; i++){ 
       $('#batch_detail').append('<li>address: ' + dat.location[i].geoaddr_mdt + 'flag: ' + dat.location[i].flag_mdt+'</li>'); 
       $('#id_mdt').val(dat.location[i].id_mdt); 
       $('#entrytype').val(dat.location[i].idedt_mdt); 
       $('#name').val(dat.location[i].name_mdt); 
       $('#geo_addr').val(dat.location[i].geoaddr_mdt); 
       $('#telephone').val(dat.location[i].telephone_mdt); 
       $('#email').val(dat.location[i].email_mdt); 
       $('#geo_detail').val(dat.location[i].displayaddr_mdt); 
       $('#website').val(dat.location[i].website_mdt); 
       //$('#active').val(dat.location[i].active_mdt); 
       var address = dat.location[i].geoaddr_mdt; 
       // if address is not empty 
       if(address != '') { 
        address_lookup(address, region, 'update'); 
       }; 
      }; 
     }; 

адрес функции поиска

function address_lookup(address, region, savetype) { 
     // set default region 
     if(region==null || region == '') { 
      region = 'uk'; 
     }; 
     // address not empty 
     if(address != '') { 
      //clear existing markers<br /> 
      if(savetype == 'save'){ 
       removemarkers(); 
      }; 
      $('#geo_detail').html('<label>Geocoding address...</label>'); 
      // lookup the address 
      geocoder.geocode({'address':address,'region':region}, function(results, status) { 
       // if the address was found 
       if(status == google.maps.GeocoderStatus.OK) { 
        $str = '<label>Geocode Successful<br> Lattitude: '+results[0].geometry.location.lat()+' Longitude: '+results[0].geometry.location.lng()+'<br> The address is displayed below and will be stored in the database.<br> If the address is incorrect you may edit it before saving the location to the database.<br>If the marker is in the wrong location you may drag it to where you believe it should be.</label>'; 
        $('#geo_detail').html($str); 
        // insert lat/long into form 
        $('#lat').val(results[0].geometry.location.lat()); 
        $('#lng').val(results[0].geometry.location.lng()); 
        // create new lat/long object 
        latlng = new google.maps.LatLng(results[0].geometry.location.lat(),results[0].geometry.location.lng()); 
        $('#disp_addr').val(address); 
        $('#form_buttons').show(); 
        $('#detail_address').show(); 
        //reverselookup(results[0].geometry.location.lat(), results[0].geometry.location.lng()); 
        // set zoom option 
        map.setZoom(15); 
        // center the map on the new location 
        map.setCenter(results[0].geometry.location); 
        createMarker(map, latlng, true, false); 
        if(savetype ='update'){ 
         savedata('update'); 
        }; 
        if(savedata='save'){ 
         savedata('save'); 
        }; 
       } else { 
        // display error 
        $('#geo_detail').append('<label>Geocoder failed to retrieve address: '+status+'</label>'); 
        $('#disp_addr').val($('#geo_addr').val()); 
       }; 
      }); 
     }; 
    }; 

EDIT в ответ на Закс 1 комментарий ----

я хочу показать каждый результат, он обрабатывается, а затем выводит результат в div geo_detail, поэтому есть список обработанной записи и ассоциированного которые возвращаются, идеально, я бы хотел, чтобы пользователь просматривал каждую запись по мере ее обработки, поэтому цикл приостанавливается до тех пор, пока пользователь не закроет кнопку сохранения, которая, возможно, установит глобальный var в true, который мой цикл будет проверять и ждать, b ut, чтобы начать с того, что мне нужна какая-то пауза, чтобы различные вызовы ajax успевали выполнить перед обработкой следующей записи.

END EDIT ------------------------------ какие-либо идеи или указатели были бы оценены

спасибо

+0

Какова ваша цель? Чтобы показывать все результаты по одному (например, один раз в 5 секунд) или показывать список результатов? –

+0

hi zack, см. Мое редактирование в исходном вопросе ... –

ответ

1

Я не думаю, что «все работает слишком быстро» - это точный диагноз любой проблемы, с которой вы сталкиваетесь.

Одна вещь, которую я вижу, заключается в том, что вы вызываете аякс-вызовы из успеха fn других вызовов ajax. Я не знаю, является ли ajax lib повторным. Вы можете этого избежать.

То, как я это сделаю, это ввести асинхронность в микс. Используйте setTimeout() для вызова функции processbatch(). Затем он будет выполняться асинхронно в отношении первого вызова ajax.

Также рассмотрите возможность использования асинхронности для вызова goecoder. Отправьте новый запрос геокодера только после завершения всех запросов геокодера. Как вы это делаете, вы отправляете их сразу. (Возможно, это то, что вы подразумеваете под «все работает слишком быстро»).

Способ для этого: принять в адрес address_lookup fn массив адресных объектов и индекс. Вызовите геокодер на i-м адресе. Затем, когда вызов завершается (успех или сбой), увеличивайте индекс и используйте setTimeout для повторного вызова address_lookup.

Таким образом, у вас всегда есть не более одного непогашенного звонка на геокодер.

Это выглядит, как это в коде:

var delay = 140; 
function doAllAddresses(a, ix, callback) { 

    // handle any addresses. 
    // Test the list index for validity. If valid, 
    // Do the geocode, then increment the list index, 
    // and call "myself" to handle additional 
    // addresses. When no more addresses remain, invoke 
    // the 'done' callback. 

    if (ix < a.length) { 
     invokeGeocoderForOneAddress(a[ix], function() { 
      // success function - gets invoked only when call to geocoder returns 
      ix++; 
      setTimeout(function(){doAllAddresses(ltr, ix, callback);}, delay); 
     }); 
     return; 
    } 

    callback(); 
} 

// kickoff: 
doAllAddresses(addresses, 0, function() { alert("all addresses are done.");}); 

EDIT
пс: Я рекомендую вам FixUp вашего Fn именование использовать верблюжье и verbNoun именования. Итак, processBatch() и lookupAddress(), а не processbatch() и address_lookup().


EDIT
Вот как об этом думать: когда вы вызываете вызов Ajax, вы сообщаете браузеру, чтобы отправить запрос HTTP. Обычно во время вызова вызова вы передаете функцию «успех», которая вызывается для вас, когда получен ответ HTTP. Как вы знаете, используя браузер, ответ может прибыть быстро или не так быстро. Когда вы вызываете вызовы ajax в цикле, вы говорите браузеру отправлять N одновременных HTTP-запросов. Не обязательно то, что вы хотите.

Я предлагаю здесь вызвать один вызов AJAX за один раз (например, геокодеру) и только вызывать следующий из успеха fn, то есть ПОСЛЕ ответа, полученного от первый. Кроме того, если вы сделаете это с помощью setTimeout(), вы избежите глубокого вложенности fn.

+0

спасибо за ваш ответ cheeso Первоначальный вызов - это вызов ajax, который возвращает данные json, мне нужно будет запустить эту функцию из этой функции успеха? Я предполагаю, что a - счет объекта json, ix - это какой-то базовый индекс, такой как 0, чтобы начать подсчет? извините, но я действительно не понимаю код. и я не уверен, что мне нужно установить в качестве функции обратного вызова –

+0

Нет - вызывать этот fn (который равно ~ так же, как ваш 'processbatch()') асинхронно (используя setTimeout) из успеха fn исходного вызова ajax. a - массив, ix - индекс в массиве. Пример стартового кода см. В приведенном выше коде, в комментарии, читающем «kickoff». Обратный вызов - это fn, который вызывается, когда все адреса обрабатываются геокодером. Просто побочный комментарий - очень полезно понимать асинхронное программирование в Javascript. Потратьте время, чтобы понять это, и вы будете счастливы, что сделали. Это важно для того, чтобы иметь возможность успешно выполнять AJAX. – Cheeso

+0

ОК спасибо за разъяснение, я попробую и посмотрю, как я нахожусь! –

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