Javascript 等待函数完成 - 执行是异步的(不按顺序)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31141894/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:18:16  来源:igfitidea点击:

Waiting for function to finish - execution is asynchronous (not in order)

javascriptjquery

提问by tamiros

I'm trying to get user's city and country before moving on with my code. It seems as if javascript is not executed in the order I need.

在继续使用我的代码之前,我正在尝试获取用户的城市和国家/地区。似乎 javascript 没有按照我需要的顺序执行。

$(document).ready(function() {    
  var country, city = '';

  function geoData() {
    $.getJSON('http://ipinfo.io/json?callback=?', function (data) { 
      console.log('step 1');
      country = data.country;
      city = data.city;
      console.log('step 2');
    });
  };

  geoData();        
  console.log('step 3');

  /* rest of the code */
});

I want the code to be executed as:

我希望代码被执行为:

step 1
step 2
step 3

However when I run the script I get:

但是,当我运行脚本时,我得到:

step 3
step 1
step 2

Why is the code running in an asynchronous way? Any suggestions how I can fix it?

为什么代码以异步方式运行?任何建议我如何解决它?

Thanks.

谢谢。

回答by Rory McCrossan

AJAX requests are asynchronous - it's what the first A stands for. If you have logic that depends on the data returned by the request, it needs to be placed within the callback function. Try this:

AJAX 请求是异步的——这就是第一个 A 代表的意思。如果您有依赖于请求返回的数据的逻辑,则需要将其放置在回调函数中。尝试这个:

var country, city = '';

function geoData() {
    $.getJSON('http://ipinfo.io/json?callback=?', function (data) { 
        console.log('step 1');
        country = data.country;
        city = data.city;
        console.log('step 2');

        step3();
    });
};

function step3() {
    console.log('step 3');
}

geoData();

An alternative is to use a promise, although the logic flow is roughly equivalent:

另一种方法是使用承诺,尽管逻辑流程大致相同:

var country, city = '';

function geoData() {
    return $.getJSON('http://ipinfo.io/json?callback=?', function (data) { 
        console.log('step 1');
        country = data.country;
        city = data.city;
        console.log('step 2');
    });
};

var deferred = geoData();
$.when(deferred).done(function() {
    console.log('step 3');
});

回答by Tomuke

Use jQuery promises to get your desired result, like so:

使用 jQuery 承诺来获得你想要的结果,像这样:

var geoDataRequest = function () {

    var deferred = $.Deferred();

     $.getJSON('http://ipinfo.io/json?callback=?', function (data) { 
         deferred.resolve(data);
     });

    return deferred.promise();
};

var somefunction = function () {

    // This will return a promise
    var getGeoData = geoDataRequest ();

    // The appropriate function will be called based on if the promise is resolved or rejected through the success and error functions in the AJAX request
    getGeoData.then(

        // Done response
        function (result) {
            alert("Success! ");
            // Enter logic here for step 2 and 3
        },

        // Fail response
        function (xhr, status, errorThrown) {
            // Handle errors here...
        }
    );
};

somefunction();

In addition, you can now use your geoDataRequestwhenever you like, and handle the results differently if you like!

此外,您现在可以随时使用geoDataRequest,并根据需要以不同的方式处理结果!