jQuery同步REST API调用无法返回对象



我正在主线程中进行同步REST API调用。jQuery(或浏览器?)抱怨。但是我不知道如何异步编码它,或者至少在读取时,代码不那么令人困惑。

这是我正在做的事情的简化版本:

<html>
    <head>
        <script type="text/javascript" src="/js/jquery.min.js" ></script>
    </head>
    <body>
        <script type="text/javascript">
            function get_foobar(val1, val2){ 
                $.ajax({
                    url: 'http://localhost:8000/api/' + va1 + '/' + val2,
                    success: function (data) {
                       let my_object = $.parseJSON(data)
                       //console.log(data);
                       console.log(my_object);
                       let params = my_object['params'];
                       let blob = my_object['the_thing'];
                       var foobar = new FooBar(var1, var2, params, blob);
                       return foobar;  // <- object created here ...
                    },
                    async: false                    
                });
            }
            $(document.ready(function(){
                foobar = get_foobar($('#field1').val, $('#field2').val());
                console.log(foobar); // <- undefined here ... wtf?
            });
        </script>
    </body>
</html>

为什么函数不返回创建的foobar对象?

这里有几个问题。

  1. 您没有在get_foobar中返回任何内容。
  2. 您无法访问成功回调的返回值。
  3. 您永远不要使用async: false

解决此问题的常见方法是使用Promises

function get_foobar(val1, val2) {
    return new Promise(function(resolve, reject) {
        $.ajax({
            url: 'http://localhost:8000/api/' + va1 + '/' + val2,
            success: function (data) {
               let my_object = $.parseJSON(data)
               //console.log(data);
               console.log(my_object);
               let params = my_object['params'];
               let blob = my_object['the_thing'];
               var foobar = new FooBar(var1, var2, params, blob);
               resolve(foobar);  // <- resolve the object created here ...
            },
            error: function(err) {
                reject(err); // REJECT any errors that occur in request
            }              
        });
    });
}
get_foobar($('#field1').val, $('#field2').val())
    .then(function(foobar) {
        console.log(foobar)
    })
    .catch(function(error) {
        console.error('something went wrong!', error);
    });

回调上的解决方案:

<html>
    <head>
        <script type="text/javascript" src="/js/jquery.min.js" ></script>
    </head>
    <body>
        <script type="text/javascript">
            function get_foobar(val1, val2, cb){ 
                $.ajax({
                    url: 'http://localhost:8000/api/' + va1 + '/' + val2,
                    success: function (data) {
                       let my_object = $.parseJSON(data)
                       //console.log(data);
                       console.log(my_object);
                       let params = my_object['params'];
                       let blob = my_object['the_thing'];
                       var foobar = new FooBar(var1, var2, params, blob);
                       cb(foobar);
                    },
                    //async: false//no reason to use it
                });
            }
            $(document.ready(function(){
                get_foobar($('#field1').val, $('#field2').val(), function(foobar){
                    console.log(foobar);
                });
            });
        </script>
    </body>
</html>

以下是一个示例,显示了您面临的问题,以及适当地获取数据的正确方法(不幸的是,同步提出Ajax请求是不好的练习,并且支持它的支持将从浏览器中从浏览器中删除。未来,所以您绝对不应该依靠它)。

主要问题是,到您的异步代码运行时,称为它的功能早就运行并已经返回。在此示例中,您需要一个像timer1这样的函数来返回结果,但是它将结果返回到setTimeout的内部代码,实际上是从那里调用的。setTimeout什么都没有返回(因此undefined)。您需要做的是使用承诺或简单的情况,回调。下面代码中的第二个示例使用回调在异步操作后运行其他代码。

我建议您阅读此信息:https://developer.mozilla.org/en-us/docs/web/javascript/eventloop。它将帮助您了解JavaScript中的异步代码,以及为什么事情以它们的工作方式工作。

var log = (function(){
  var out = document.querySelector('#out');
  return function(msg){
    out.innerHTML += '<div>' + msg + '</div>';
  }
})();
function getSomethingAsyncTheWrongWay(){
  setTimeout(function timer1(){
    log('Round 1: First in code, last in console');
    return 'Result';
  }, 1000);
}
log(getSomethingAsyncTheWrongWay());
log('Round 1: Last in code, first in console');
function getSomethingAsyncTheRightWay(callback){
  setTimeout(function timer2(){
    log('Round 2: First in code, last in console');
    callback('Result');
  }, 1000);
}
getSomethingAsyncTheRightWay(function(result){
  log(result);
});
log('Round 2: Last in code, first in console');
#out{
  color:green;
  background:#000;
  font-family:courier new;
  padding:1em;
  font-weight:bold;
}
<div id=out></div>

您将无法将'Blobby'直接返回到内存变量。

将" blobby"传递到全局变量。

尝试以下一个:

jQuery-将AJAX响应存储到全局变量

jQuery-将ajax json响应存储为变量

最新更新