【问题标题】:Wait for the end of an asynchrounous call in a JS function. (jQuery.Deferred ?)等待 JS 函数中的异步调用结束。 (jQuery.延迟?)
【发布时间】:2014-09-20 14:01:22
【问题描述】:

这是我的(简单)问题:

我有一个 Javascript 函数,它调用外部 API 以异步获取一些结果。我需要等待这些结果,因为我想对它们进行一些测试以确定它们是否有效,但Deferred 对我来说非常复杂,我无法成功。

这是我所做的:

$("#step-content").steps({
    //some parameters
    onStepChanging: function(event, currentIndex, newIndex) {
        verifyAddress().done(function(test) {
            if($("#hdnLatitude").val() == "" || $("#hdnLongitude").val() == "")
                test = false;
            else
                test = true;

            console.log(test); // test is true or false, that's good
            return test;
        });

        console.log(test); // test is always empty here

        //Here, I just need to do return true or return false to block step-changing if there is an error.
        return test;
    }
});

基本上,这是我的verifyAddress 函数:

function verifyAddress() {
    var r = $.Deferred();

    var geocoder = new google.maps.Geocoder();
        if (geocoder) {
            var adressToGeocode = /* Get the address to geocode */

            geocoder.geocode({ 'address': adressToGeocode }, function (results, status) {
                if (status == google.maps.GeocoderStatus.OK) 
                {
                    //Save the lat/lng returned in #hdnLatitude and #hdnLongitude
                }

                r.resolve();
            });
        }
    //Not sure where to place the return r ; try elsewhere but no success
    return r;
}

所以我需要等待verifyAdress() 结束并填充#hdnLatitude#hdnLongitude,然后在onStepChanging 事件中返回true 或false确定我们是否可以进行下一步(地址是可以的)而不是(地址是错误的)

我使用this SO question 来更好地理解Deferred,但我无法成功。
有人可以帮助我吗?

非常感谢

【问题讨论】:

  • 如何从异步函数返回。经典。看看here,了解为什么你做不到。
  • 嗨。我知道这对于像我这样的初学者来说是一个经典问题,但我真的需要帮助来理解这个问题。我看过这个链接,我是否必须将回调传递给我的 verifyAddress() 方法?我无法理解底层逻辑......
  • @guest271314:以this question 为例。无论您是采用回调还是返回延迟都没有区别,您无法从 onStepChanging 方法同步 return true/false
  • @AlexB:是的,这真的是不可能的。您不能忙于等待异步结果。您的问题的解决方案是选择一个不同的steps插件,一个可以处理异步功能的插件。
  • 这是另一个解释异步性质的问题:stackoverflow.com/questions/23667086/…。问题是您使用的是第三方库,它期望代码是同步的。当需要同步代码时,您不能使用异步代码。正如 Bergi 所说,您需要找到另一个插件。

标签: javascript jquery asynchronous jquery-deferred deferred


【解决方案1】:

你的函数应该是这样的:

function verifyAddress() {
    var r = $.Deferred();

    //call Google server to geocode my address. The call is asynchrounous.
    //The results are put in #hdnLatitude and #hdnLongitude fields.
    //The fields are correctly filled.
    googleFunc(someParam, function done(){
      r.resolve();
    });

    return r;
}

你必须在一些done回调中解决延迟,这些回调将被谷歌服务器函数调用,必须有一些回调函数来处理结果。

var test = false; //Can't change step until allowed in async function   
$("#step-content").steps({
    //some parameters
    onStepChanging: function(event, currentIndex, newIndex) {
    if (!test)
      verifyAddress().done(function() {
            if($("#hdnLatitude").val() == "" || $("#hdnLongitude").val() == "")
                test = false;
            else
                test = true;

            console.log(test); // test is true or false, that's good

            //Auto move to next step if test is true
        });


        //Here, I just need to do return true or return false to block step-changing if there is an error.
        return test;
    }
});

【讨论】:

  • 请查看我更新的问题。在我看来,这就是我所做的;但是,这不起作用?你能指出我哪里错了吗?
  • @VitaliyG:您更新的代码似乎不起作用。您不能在 异步 回调中分配给 test,然后分配给 expect it to be set when you return
  • 步进必须执行两次,一次启动异步功能,一次完成后。第二次可以从异步回调中启动。
  • 我可能遗漏了一些东西,但是测试总是错误的,因为它已经被定义为假,即使它应该是真的......
  • @AlexB:verifyAddress 完成后 - 将来,而不是您在代码中检查它的时候。如果您有一个 javascript 控制台,并且当 verifyAddress 完成时,您可以在控制台中手动输入 alert(test) 以检查该值。
【解决方案2】:

好的,正如@Bergi 所说,使用这个插件似乎是不可能的。

所以,我绕过了这个问题,将Next 按钮替换为一个调用我的异步事件的假按钮。在此事件结束时,如果结果正常,我将Next 按钮替换为我克隆的原始按钮并在其上触发click 事件以传递到下一步,而无需用户单击两次。

不知道它是否真的很干净,但它可以满足我的需求

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多