【问题标题】:How to make the getJSON wait before running the rest of the code?如何在运行其余代码之前让 getJSON 等待?
【发布时间】:2017-03-08 15:35:16
【问题描述】:

我写了一个简单的函数来确定你的城市位置。但是,我想知道是否有办法强制函数等待 getJSON 然后移动到下一行代码?在示例中,您将看到它显示“警报 1”跳过“警报 2”并直接转到“警报 3”,然后显示“警报 2”。提前谢谢你。

最好的问候, 乔治

var Alpha;

function Location(){
	alert(Alpha + " 1");
	$.getJSON("http://freegeoip.net/json/?callback=?", function(location){
		Alpha = location.city;
		alert(Alpha + " 2");
	});	
	alert(Alpha + " 3");
}

$(document).ready(function() {
	Location();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【问题讨论】:

  • 您可以使用承诺或回调。 getJSON 与您的代码是异步的。
  • 你为什么不把代码移到你的回调中?

标签: javascript jquery json getjson


【解决方案1】:

在您的代码中,getJSON 异步返回结果。这意味着代码将在执行发生时继续运行。

您可以将代码移动到成功回调,以确保在返回结果之前没有任何运行:

var Alpha;

function Location(){
    alert(Alpha + " 1");
    $.getJSON("http://freegeoip.net/json/?callback=?", function(location){
        Alpha = location.city;
        whenDone();
    }); 
}

function whenDone() {
    alert(Alpha + " 2");
    alert(Alpha + " 3");
}

$(document).ready(function() {
    Location();
});

在较新的 JavaScript 版本中,您可以利用 async/await 和 Promises 的强大功能以某种方式“等待”执行:

let Alpha;

function Location() {
  return new Promise((resolve, reject) => {
    $.getJSON("http://freegeoip.net/json/?callback=?", location => {
      resolve(location);
    }); 
  }
}

async function init() {
  try {
    let location = await Location();
    Alpha = location.city;
  } catch(error) {
    console.error(error);
  }
}

$(document).ready(function() {
  init();
});

这将需要你 polyfill 一些特性。

注意:较新版本的 jQuery 返回一个 Promise 兼容接口,您可以使用它来等待。我还没有尝试过,但是将调用包装在 Promise 中无论如何都适用于旧版本。

【讨论】:

    【解决方案2】:

    您可以指定在 $.getJson 完成后运行的代码。这是 jQuery 文档中的一个示例。

    var jqxhr = $.getJSON( "example.json", function() {
      console.log( "success" );
      })
      .done(function() {
        console.log( "second success" );
      })
      .fail(function() {
        console.log( "error" );
      })
      .always(function() {
        console.log( "complete" );
      });
    

    jQuery Docs

    【讨论】:

      【解决方案3】:

      把getJSON()调用后需要执行的逻辑放在回调函数中,就是函数的意图,像这样:

      var Alpha;
      function ineedtorunmorecode(){
          alert(Alpha + " 4");
      }
      
      function Location(){
          alert(Alpha + " 1");
          $.getJSON("http://freegeoip.net/json/?callback=?", function(location){
              Alpha = location.city;
              alert(Alpha + " 2");
              alert(Alpha + " 3");
              ineedtorunmorecode();
          }); 
      }
      
      $(document).ready(function() {
          Location();
      });
      

      【讨论】:

        【解决方案4】:

        无法让调用getJSON 的函数等待。这样做会违背 JavaScript 用于异步事件的模型。在调用完成时要执行的任何代码都必须在(或从)回调之一中调用。 (或者你可以使用 Promise API,它在底层是一样的,但语法更好......)

        【讨论】:

          【解决方案5】:

          因为它是异步的,所以函数不会等待,但您可以通过以下方法清理代码:

          var Alpha;
          
          function Location(){
          	alert(Alpha + " 1");
          
             var onSuccess = function(location) {
                          Alpha = location.city;
          		             alert(Alpha + " 2");
              }
          	$.getJSON("http://freegeoip.net/json/?callback=?", onSuccess);	
            
                  
          }
          
          $(document).ready(function() {
          	Location();
          });
          <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

          【讨论】:

            【解决方案6】:

            不幸的是,在 javascript 中没有简单的等待方法。你必须使用回调函数。

            【讨论】:

              【解决方案7】:

              the documentation的例子中提到,当$.getJSONdone时,你可以执行代码。在这里你可以看到这个例子。我添加了一些console.log 来向您展示代码是如何执行的。

              (function() {
                console.log("Start Snippet");
                var flickerAPI = "http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?";
                console.log("Start Load");
                $.getJSON( flickerAPI, {
                  tags: "mount rainier",
                  tagmode: "any",
                  format: "json"
                })
                  .done(function( data ) {
                    console.log("End Load");
                    $.each( data.items, function( i, item ) {
                      $( "<img>" ).attr( "src", item.media.m ).appendTo( "#images" );
                      if ( i === 3 ) {
                        return false;
                      }
                    });
                  });
                console.log("End Snippet");
              })();
              img {
                height: 100px;
                float: left;
              }
              <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
              <div id="images"></div>

              【讨论】:

                【解决方案8】:

                getJSON() 是一个简写的 Ajax 函数,所以, $.ajaxSetup({async : false});会成功的

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-10-20
                  • 1970-01-01
                  • 2019-12-24
                  • 1970-01-01
                  • 2017-11-28
                  相关资源
                  最近更新 更多