【问题标题】:Asynchronous coordinate grabbing before submitting form提交表单前异步坐标抓取
【发布时间】:2018-09-11 14:55:49
【问题描述】:

我正在尝试提交一个位置的输入字段,通过谷歌地理编码器查找纬度和经度,将它们放在一些隐藏字段中,然后作为表单发布。

有两个主要障碍,第一个是我的 validateFields 函数看不到添加到隐藏文本框中的值,第二个是延迟提交表单以添加 long 和 lat 作为发帖。

我知道可以让提交事件返回 true 或 false 以根据 validateField 检查延迟提交,但即使使用 Chrome 开发工具我看到它们已添加,它似乎也永远看不到坐标。

$('#LocationSearchForm').submit(event => {
    let input = $('#SearchTerm').val();
    $('#Longitude'.val('23423'));
    $('#Latitude'.val('1111'));
    getLatLong().then(allowSubmit);
});

function getLatLong(input) {
    return new Promise(resolve => {
        let geocoder = new google.maps.Geocoder();
        geocoder.geocode({ address: input }, (results, status) => {
            if (status == google.maps.GeocoderStatus.OK) {
                $('#Latitude').val(results[0].geometry.location.lat());
                $('#Longitude').val(results[0].geometry.location.lng());
            }
        });
        resolve(console.log(`applied coordinates to hidden fields`));
    });
}

function validateFields() {
    if ($('#Latitude').val() === '' && $('#Longitude').val() === '') {
        return false;
    }
    return true;
}

function allowSubmit() {
    return validateFields();
}

HTML

<form id="LocationSearchForm" action="POST">
    <input id="SearchTerm" type="text" placeholder="Find a city" value>
    <input id="Latitude" type="hidden" value>
    <input id="Longitude" type="hidden" value>
</form>

【问题讨论】:

  • 您需要从事件处理程序本身返回 true 或 false。 allowSubmit 函数返回什么并不重要。您需要始终阻止表单在该事件上提交,然后验证,然后在可以提交表单时提交。

标签: javascript jquery asynchronous post promise


【解决方案1】:

首先您需要将resolve() 移动到geocode 回调中。现在它正在立即解决,但 geocode() 是异步的。

geocoder.geocode({ address: input}, (results, status) => {
  if (status == google.maps.GeocoderStatus.OK) {
    $('#Latitude').val(results[0].geometry.location.lat());
    $('#Longitude').val(results[0].geometry.location.lng());
    // resolve now that data updated
    resolve(console.log(`applied coordinates to hidden fields`));
  } else {
    // reject here
  }
});

submit 回调中,您需要防止立即提交,以便为异步操作留出时间。一旦承诺解决,您就可以使用本机提交

$('#LocationSearchForm').submit(function(event){
    event.preventDefault()
    let form = this;

    getLatLong().then(function(){
      if(validateFields()){
         // use native submit to by-pass jQuery listener
         form.submit()
      }else{
          // alert user of problems
      }
    }).catch(function(err){ /*do something for geocode rejection */});
});

【讨论】:

    【解决方案2】:

    非常感谢各位。作为参考,我在@charlietfl 的回答的帮助下以这种方式工作。

    $('#LocationSearchForm').submit(event => {
        event.preventDefault();
        let input = $('#SearchTerm').val();
    
        getLatLong(input)
            .then(() => {
                return !validateFields() ? $('form')[0].submit() : null;
            })
            .catch(err => {
                console.log(err);
            });
    });
    
    function getLatLong(input) {
        return new Promise((resolve, reject) => {
            let geocoder = new google.maps.Geocoder();
            geocoder.geocode({ address: input }, (results, status) => {
                if (status == google.maps.GeocoderStatus.OK) {
                    $('#Latitude').val(results[0].geometry.location.lat());
                    $('#Longitude').val(results[0].geometry.location.lng());
                    resolve(true);
                } else {
                    reject(false);
                }
            });
        });
    }
    
    function validateFields() {
        return $('#Latitude').val() === '' && $('#Longitude').val() === '';
    }
    

    使用“this”对我不起作用,但可能是因为我坚持使用箭头函数,在与 jQuery 混合时这会是不好的做法吗?我尝试了$('#LocationSearchForm'),但不起作用,所以我不得不改用$('form')[0].submit(),但我不确定提交这样的表单是否是一种好习惯。

    感谢@Bergi 对提交建议的布尔返回,与使用明确的submit()preventDefault 相比,这似乎是延迟提交的一种很好的替代方法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-22
      • 2018-10-18
      • 2013-05-01
      • 1970-01-01
      相关资源
      最近更新 更多