【问题标题】:jQuery .done not returning as expectedjQuery .done 没有按预期返回
【发布时间】:2016-10-22 00:09:54
【问题描述】:

我知道这是我的一个误解,我正在努力了解我做错了什么,我真的可以使用一些帮助。

我有一个成功的 ajax 请求并返回数据就好了。 Api 返回一个错误代码,然后我尝试根据给定的代码返回响应,除了该函数仅返回 ajax 调用传递的内容。

function getData(){
    var promise = $.ajax({
       url: 'api.php',
       type: 'POST',
       dataType: 'json'
    });
    return promise.done(function(data){
        console.log(data);
        if(data.errorCode === 0){
            return data;
        } else {
            return 'failed';
        }
    });
}
$(document).ready(function(){
   $('.btn').click(function(){
       var apiData = getData();
       console.log(apiData);
   });
});

所以如果 api 返回一个非 0 的错误代码,那么函数 getData 应该返回一个“失败”字符串,除了它返回数据元素。我知道代码不是0,因为console.log显示代码是999。我做错了什么?为什么我不能让它返回我的“失败”字符串?

【问题讨论】:

  • 发布您如何使用 getData。
  • dfsq 所说的。特别是,如果您正在执行if (getData() == "failed") 并期望它表明它失败了,那就是问题所在。 getData 返回一个 promise(jQuery 风格),而不是 data 或 "failed"。
  • 你永远不能直接从异步调用中返回。 Promise 并不是什么魔法,可以让这一切变得不那么真实。 getData() 的调用者不会立即访问结果。你能做的最好的就是从回调中恢复你的逻辑。无论你是否使用 Promises,都是如此。
  • 更新了代码以显示我是如何调用 getData() 函数的。
  • TJ,所以如果我理解这一点的话。 if 语句中的第一个 return 是我的字符串,然后 promise.done() 的 return 覆盖第一个 return 并将其更改为 .done() 传递的数据。所以它是这样做的;返回='失败';返回 = 数据;

标签: javascript jquery ajax promise


【解决方案1】:

getData 不(也不能)返回数据或"failed";它返回一个承诺。你像在getData 中所做的那样消耗这个承诺:

$(document).ready(function(){
   $('.btn').click(function(){
       getData().done(function(apiData) {   // **
           console.log(apiData);            // **
       });                                  // **
   });
});

在该回调中,apiData 将是您在 getData 中返回的任何回调,因此它将是数据对象或字符串 "failed"。

(我在那里使用了done,因为它是你在其他地方使用的,但通常我会使用then,标准的promise函数。)

关于 Promise 要理解的关键点之一是 then(和 done)返回一个新的 Promise(从技术上讲,对于真正的 Promise,一个 thenable ) 将根据回调的作用来解决。

所以考虑一下(让我们暂时坚持使用 jQuery 的 Deferred):

function doSomething() {
  var d = $.Deferred();
  setTimeout(function() {
    // Resolve our promise with "a"
    d.resolve("a");
  }, 10);
  return d.promise();
}

// Consume the promise and put it through a chain:
doSomething()
  .then(function(result) {
    // This callback happens to do synchronous processing
    console.log("First callback got", result);
    return result.toUpperCase();
  })
  .then(function(result) {
    // This one does something async, and so it returns a promise
    var cd = $.Deferred();
    setTimeout(function() {
      console.log("Second callback got", result);
      cd.resolve(result + result);
    }, 10);
    return cd.promise();
  })
  .then(function(result) {
    console.log("Third callback got", result);
  });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

输出是

第一个回调得到了 第二个回调得到 A 第三次回调得到AA

现在,我之前说过then 总是返回一个承诺(thenable)。当我的第一个回调是同步的并直接返回一个值,但我的第二个回调是异步的并返回一个承诺时,它是如何做到的? then 函数查看回调的返回值,如果它是“thenable”(带有then 的东西),则返回它;如果它不可用,它会创建一个新的、已解决的 Promise,并将该值作为分辨率值。


为了完整起见,这是上面带有原生 JavaScript 承诺的示例(需要浏览器支持):

function doSomething() {
  return new Promise(function(resolve) {
    setTimeout(function() {
      // Resolve our promise with "a"
      resolve("a");
    }, 10);
  });
}

// Consume the promise and put it through a chain:
doSomething()
  .then(function(result) {
    // This callback happens to do synchronous processing
    console.log("First callback got", result);
    return result.toUpperCase();
  })
  .then(function(result) {
    // This one does something async, and so it returns a promise
    return new Promise(function(resolve) {
      setTimeout(function() {
        console.log("Second callback got", result);
        resolve(result + result);
      }, 10);
    });
  })
  .then(function(result) {
    console.log("Third callback got", result);
  });

输出是

第一个回调得到了 第二个回调得到 A 第三次回调得到AA

【讨论】:

    【解决方案2】:

    根据http://api.jquery.com/jquery.ajax/ 文档,您可以链接.done, .fail, .always or .then。

    $(document).ready(function() {
      $('.btn').click(function() {
        $.ajax({
           url: 'api.php',
           type: 'POST',
           dataType: 'json'
        })
        .done(function(data) {
            console.log(data);
            if (data.errorCode === 0) {
                console.log(data)
            } else {
                console.log(data)
            }
        });
      });
    });
    

    这会起作用

    【讨论】:

      猜你喜欢
      • 2015-02-11
      • 2013-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-06
      • 2020-06-28
      相关资源
      最近更新 更多