【问题标题】:jQuery deferred : use to delay return of function until async call within function complete + get return valuejQuery deferred:用于延迟函数的返回,直到函数内的异步调用完成+获取返回值
【发布时间】:2012-07-11 18:41:07
【问题描述】:

如何正确使用 jQuery deferreds 来延迟函数的返回,直到函数内的异步调用完成 + 获取返回值?

这是我当前的代码:

function getFields(page)
{
  var dff = $.Deferred();
  result = {};
  $.ajax( //the async call
    {
      url: page,
      success:
        function (data)
        {
          //work out values for field1 & field 2 from data here
          result = 
          {
            'field1' : field1,
            'field2' : field2
          };
        },
      complete:
        function()
        {
          dff.resolve(result); //my attempt to return the result
        }
    }
  );
  return dff.promise();
}

我想打印 {"field1":"value1","field2":"value2"}

var result = getFields('http://something');
console.log(JSON.stringify(result)); 

但是,结果的值似乎是一个 jQuery 对象 - 所以我做错了什么,但是什么?

谢谢!


附:抱歉新手问题,我是第一次使用deferreds,所以我仍然掌握基本概念。

【问题讨论】:

    标签: javascript jquery asynchronous jquery-deferred


    【解决方案1】:

    延迟getFields 函数返回的唯一方法是将AJAX async 属性设置为false:

       var ajaxPromise = $.ajax(
        {
          url: page,
          async: false  // make the call synchronous
        }
      );
    

    但 jQuery 文档指出,从 1.8 开始已弃用(即不鼓励使用它)。

    Deferred 不会使 AJAX 同步,而是让回调和异步方法更容易使用。

    据我所知,你正在尝试做这样的事情可能会更好:

    function getFields(page)
    {
      var ajaxPromise = $.ajax( //the async call
        {
          url: page
        }
      );
    
      var dff = $.Deferred();
      ajaxPromise.then(function(data){
    
        // Possibly access the loaded data in this function.
        var result = {
          'field1' : field1,
          'field2' : field2
        };
    
        // Notify listeners that the AJAX call completed successfully.
        dff.resolve(result);
    
      }, function(){
        // Something went wrong - notify listeners:
        dff.reject(/* possibly pass information about the error */);
      });
    
      return dff.promise();
    }
    

    然后像这样使用 promise 对象:

    var fieldPromise = getFields('http://something');
    fieldPromise.done(function(result){
      console.log(JSON.stringify(result)); 
    });
    

    请注意,getFields 会立即返回一个 Promise 对象,但您必须等待 promise 解决后才能注销结果。

    【讨论】:

    • @Sly_caridnal:+1 并检查 - 很好的解释!
    • Oooh, nice... 将 dff.resolve(data); 包裹在 setTimeout 中是模拟慢速 ajax 调用的一种快速简便的方法(因为我正在测试的内容在前后不一致)第二个ajax调用)
    • 其实有一个办法:改变getFields(page)函数的return语句,比如return dff.promise().getState() == 'resolved'它会暂停直到resolve或reject发生。当然,您可以只返回 Promise 对象本身并在其他地方检查状态。
    • @shuangwhywhy - 没有 getState() 方法,只有 state() 并且它根本不会暂停。它只是返回“待处理”。
    【解决方案2】:

    这里是 deferreds 的基本思想:你返回一个对象,你可以用它来定义当返回值返回时将被调用的函数。所以你可以这样做:

    function getFields(page)
    {
        return $.ajax(page);
    }
    

    然后你就可以调用它,并指定XHR调用完成时要调用的函数:

    var jqXHR = getFields("/path/to/call");
    jqXHR.done(function (data) { alert(JSON.stringify(data); });
    

    对象是可链接的,所以你可以这样做:

    getFields("/path/to/call")
        .done(function (data) { alert(JSON.stringify(data); });
    

    注意$.ajax返回的jqXHR对象是一个Deferred-compatible对象,所以你可以阅读http://api.jquery.com/category/deferred-object/的文档。

    我不确定您的示例代码是什么意思(因为它实际上并没有使用 Ajax 调用)但也许您的意思是这样的:

    function getFields()
    {
        var df = $.Deferred();
        window.setTimeout(function () {
            df.resolve({field1: "value1", field2: "value2"});
        }, 1000);
        return df.promise();
    }
    
    getFields().done(function (data) { console.log(JSON.stringify(data)); });
    

    这将在您运行后一秒钟打印出您想要的值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-21
      • 2017-01-19
      • 2011-09-14
      • 1970-01-01
      • 2014-05-28
      • 1970-01-01
      • 2015-08-24
      • 1970-01-01
      相关资源
      最近更新 更多