在javascript / jquery中执行函数

时间:2015-01-08 14:25:20

标签: javascript jquery ajax

我有一个让用户拉长的功能。我需要根据用户位置返回一个url,url会有所不同。返回的url用于ajax调用。然而,第二个ajax调用在我的第一个函数完成之前被命中,然后在未定义url的情况下给出404.

所以我的代码是:

$(document).ready(function () {
   getLatLong();

   if (!hasTicket) {
        doAction();
    } else {
        doAnotherAction();
        $.unblockUI();
    }
});

function doAction() {
         $.ajax({
            url: url, // this is where I am failing
            type: 'POST',
            success: function (response) {
                ticket = response.data.ticket;
                $.unblockUI();
            },
            error: function (xhr) {
                $.unblockUI();
                errorHandler("Failed" + xhr.status);
            }
        });
}

function getLatLong() {
    if (Modernizr.geolocation) {
        navigator.geolocation.getCurrentPosition(
            function (position) {
                getUrl(position.coords.latitude, position.coords.longitude);
            },
            getUrlFallback,
            { enableHighAccuracy: false, timeout: 10000, maximumAge: 360000 }
        );
    } else {
        getUrlFallback();
    }
}

function getUrl(latitude, longitude) {
    $.ajax({
        url: 'api/Controller/Action',
        type: 'GET',
        async: false, // tried making this synchronous
        data: {
            latitude: latitude,
            longitude: longitude
        },
        success: function (data) {
            url = data;
        },
        error: function (xhr) {
            errorHandler("Failed to get users nearest url: " + xhr.status);
        }
    });
}

所以我调用getLatLong然后调用我的getUrl ajax函数,该函数将async设置为false但是我认为它首先从getLatLong返回,因为我的doAction函数被调用,然后url变得未定义。

如何在doAction运行之前确保getLatLong和getUrl完全完成?

我试图复制调用getLatLong()之后发生的功能;进入一个函数并使用$ .when adn .then如下所示,但在url设置之前它仍然进入doAction方法。

function callAction() {
       if (!hasTicket) {
            doAction();
        } else {
            doAnotherAction();
            $.unblockUI();
        }
}

然后我在doc中准备了以下内容:

$(document).ready(function () {

    $.when(getLatLong()).then(callAction());
});

编辑 - 使用getUrlFallback函数更新

function getUrlFallback () {
    // uses 3rd party geoPlugin
    getUrl(geoplugin_latitude(), geoplugin_longitude());
}

1 个答案:

答案 0 :(得分:1)

您可以将getLatLong调用转换为返回jQuery Promise

(注意:我在这里不包括getUrlFallback逻辑,因为您还没有包含该代码,所以我无法告诉它应该做什么):

function getLatLong() {
    return $.Deferred(function(def) {
         if (!Modernizr.geolocation) {
             def.resolve(geoplugin_latitude(), geoplugin_longitude());
         } else {
             navigator.geolocation.getCurrentPosition(
                 function(position) {
                     def.resolve(position.coords.latitude, position.coords.longitude);
                 },
                 def.resolve(geoplugin_latitude(), geopugin_longitude()),
                 { enableHighAccuracy: false, timeout: 10000, maximumAge: 360000 }
             );
         }
    }).promise();
}

并修改getUrl,使其return成为$.ajax的结果,并省略successerror回调:

function getUrl(latitude, longitude) {
    return $.ajax(...);
}

所以你现在可以使用:

getLatLong().then(getUrl).then(callAction);   // NB: no () after callAction

callAction将自动传递URL,而不是存储在外部范围的变量中。

现在请注意getLatLong函数现在具体如何做到这一点。它没有随后尝试将lat / long转换为URL,因为getUrl为您执行此操作(无论URL来自GeoAPI还是geoplugin)。