【问题标题】:How to return from asynchronous call using jquery?如何使用 jquery 从异步调用中返回?
【发布时间】:2016-03-07 09:04:31
【问题描述】:

我尝试使用回调函数,但仍然没有效果。这是 HTML:

<form action="{% url 'seller_details' %}" method="post" id="seller_details">
    {% csrf_token %}
    <div>
        <div class="heading">PERSONAL INFORMATION</div>
        <table>
            <tr>
                <td id="wd25">Full Name</td>
                <td><input type="text" placeholder="Full Name" name="full_name" value="{{full_name}}"/></td>
            </tr>
            <tr>
                <td>Mobile Number</td>
                <td><input type="text" placeholder="Mobile Number" value="{{mobile}}" name="mobile"/></td>
            </tr>
            <tr>
                <td>Store Address</td>
                <td><textarea rows="5" placeholder="Store Address" name="pickup_address" value="{{pickup_address}}"></textarea></td>
            </tr>
        </table>
</form>

然后我尝试验证表单并使用 jQuery validate 的 submit handler 提交表单

$("#seller_details").validate({
    rules: {
        full_name: "required",
        pickup_address:"required",
    },
    messages: {
        full_name: "Please enter Name",
        mobile: "Please enter Mobile Number",
       pickup_address:"Please enter address",
    },
    submitHandler: function(form){
        var form = $(form).serialize()

        codeLatLng(storeGeoAddress);

        console.log(latitude)
        console.log(longitude)

        $.ajax({        
            type: "post",
            url: "{% url 'seller_details' %}",     
            data: form + "&csrfmiddlewaretoken=" + '{{csrf_token}}' + '&latitude=' + latitude + '&longitude=' + longitude,

我使用了以下名为geocoder异步函数来获取提交地址的纬度经度

function codeLatLng(callback) {
    var address = $("textarea[name=pickup_address]").val();
    if (geocoder) {
        geocoder.geocode({'address': address}, function(results, status) {
            if (status == google.maps.GeocoderStatus.OK) {
                if (results[0]) {
                    callback(results[0]);
                } else {
                    alert("No results found");
                }
            } 
            else {
                alert("Geocoder failed due to: " + status);
            }
        });
    }
}

function storeGeoAddress(addr) {     
    latitude = addr.geometry.location.lat();
    longitude = addr.geometry.location.lng();
}

我在这里面临的问题是我无法收集纬度和经度的值,以便我可以将其返回给我的提交处理程序,以便它可以发布这些值?在这种情况下我能做什么?谢谢

纬度经度在此处全局定义

console.log(latitude) console.log(longitude) 无法记录任何内容

有什么方法可以让我提交处理程序作为我的回调函数?

【问题讨论】:

  • latitudelongitude 变量的范围是什么?如果它们在这两个函数的范围内,那么你所拥有的应该可以工作,尽管在请求的查询字符串中放置一个 JSON 字符串是相当奇怪的。你最好只发送一个普通对象并让 jQuery 为你编码。
  • 无论latitude and longitude 的范围如何,您所拥有的都不会起作用。 $.ajax 将在storeGeoAddress 回调被触发之前运行,因为storeGeoAddress 中的逻辑是异步的。您需要在回调中执行 AJAX。然后你也可以解雇讨厌的全局变量。
  • 两个变量都是全局变量
  • 那么在这种情况下提交处理程序应该是回调
  • 我可以将提交处理程序作为回调吗?

标签: jquery google-maps asynchronous geocoding


【解决方案1】:

承诺救援。

jQuery 有一个 Promise 实现,它对您的情况非常有用。这个怎么样。

首先,编写一个 geocode-Helper,它封装了 Google 的基于回调的 API 方法并返回解析地址的 promise

function geocodeAsync(addrString) {
    var result = $.Deferred();

    if ( !(geocoder && geocoder.geocode) ) {
        result.reject("geocoder not defined");
    } else {
        geocoder.geocode({address: addrString}, function (results, status) {
            if (status === google.maps.GeocoderStatus.OK) {
                if (results.length) {
                    result.resolve(results[0]);
                } else {
                    result.reject("No results found");
                }
            }
            else {
                result.reject("Geocoder failed due to: " + status);
            }
        });
    }

    return result.promise();
}

现在,事情变得容易了。您可以像使用 jQuery 的 Ajax 函数一样使用该函数:

$("#seller_details").validate({
    rules: {/* ... */},
    messages: {/* ... */},
    submitHandler: function (form) {
        var address = $(form).find("textarea[name=pickup_address]").val();

        geocodeAsync(address).done(function (geocodeResult) {
            var otherParams = {
                'parameter[]': JSON.stringify(parameter),
                csrfmiddlewaretoken: '{{csrf_token}}',
                latitude: geocodeResult.geometry.location.lat(),
                longitude: geocodeResult.geometry.location.lng()
            },
            postBody = [ $(form).serialize(), $.param(otherParams) ].join('&');

            $.post("{% url 'seller_details' %}", postBody).done(function (result) {
                // whatever you want to do on POST success
            }).fail(function (jqXhr, status, error) {
                // seller_details update failed
            });
        }).fail(function (reason) {
            alert("Geocoding failed because: " + reason);
        });
    }
});

不需要全局变量,并且在阅读代码时您会确切地看到发生了什么。

相关文档:https://api.jquery.com/jQuery.Deferred/

【讨论】:

  • else部分的结果是什么?我认为应该是 result.reject ?
  • @AdrafeRinzzler 是的,这是一个错字。我应该想到比resultresults 更好的变量名。
  • var address = $(form).find("textarea[name=pickup_address]").val();
  • postBody = [ $(form).serialize(), $.param(otherParams) ].join('&');说 unrecognized exp ...为什么呢?
  • $(form).find()form.find() 不同。我在那里也看不到语法错误。 [ $(form).serialize(), $.param(otherParams) ].join('&amp;') 同样有效。您是在使用我发布的代码还是进行了更改?
【解决方案2】:

你在回调地狱!这是 javascript 中一个相当普遍的问题。从异步调用“同步”返回的方式是通过 Promise。要么这样,要么你必须传递一系列回调来处理必须发生的各种步骤。

我最喜欢的 JS Promise 实现是 https://github.com/cujojs/when,我建议您遵循本指南:http://blog.briancavalier.com/async-programming-part-1-it-s-messy/

【讨论】:

  • jquery 解决方案怎么样?
  • 我可以将提交处理程序作为回调吗?
【解决方案3】:

你仍然可以在 submitHandler 中创建回调

codeLatLng(function(addr){
    var latitude = addr.geometry.location.lat();
    var longitude = addr.geometry.location.lng();

    console.log(latitude)
    console.log(longitude)

    $.ajax(...);
});

【讨论】:

    猜你喜欢
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    相关资源
    最近更新 更多