简体   繁体   English

我错误地使用.done(),没有按预期返回值

[英]I'm using .done() incorrectly, doesn't return value as expected

I am trying to use jQuery's AJAX deferreds to return a JSON string that can be parsed and used but I have coded myself into a corner and may have screwed up the logic. 我正在尝试使用jQuery的AJAX延迟返回一个可以解析和使用的JSON字符串,但我已将自己编码到一个角落,可能搞砸了逻辑。 I expected the results of the AJAX call to be returned in the .done() callback and they are . 我期望在.done()回调中返回AJAX调用的结果, 它们是 I thought once done that I could return the result for use in the remainder of the function. 我曾经想过,我可以返回结果,以便在函数的其余部分中使用。 I know that I'm missing something really obvious and simple, I just cannot put a finger on what it is. 我知道我错过了一些非常明显和简单的东西,我只是不知道它是什么。

Here is the initial coding of the function, stil very much in test mode. 这是函数的初始编码,在测试模式下非常多。 The JSON is correctly returned in the .done() function but I cannot assign it outside of the function for use. JSON在.done()函数中正确返回,但我不能在函数外部分配它以供使用。

checkUserRoles = function(){
    var userRole, foo, roles, i$, len$, i;
    userRole = roleChecker();
    foo = userRole.done(function(data){
        var bar;
        bar = foo.responseText; // correctly returns the JSON data
        console.log(bar);
        return bar; //  is undefined, this is the problem
    });
    if (userRole !== false) {
        userRole = jsonDecode(userRole);
    } else {
        userRole = "";
    }
    roles = userRole.split(',');
    $("if-user-role").hide();
    for (i$ = 0, len$ = roles.length; i$ < len$; ++i$) {
        i = roles[i$];
        $("if-user-role[data-role~=" + i + "]").show();
    }
    return true;
};
this.roleChecker = function(){
    var retVal, allCookies, i$, len$, thecookie, hashedCookie, theHash, userHash, post;
    retVal = "";
    allCookies = document.cookie.split(';');
    for (i$ = 0, len$ = allCookies.length; i$ < len$; ++i$) {
        thecookie = allCookies[i$];
        if (thecookie.indexOf('userHash') >= 0) {
            hashedCookie = thecookie;
            theHash = hashedCookie.split('=');
            userHash = theHash[1];
        }
    }
    post = $.ajax({
        url: '/services/check_hash.php',
        data: {
            hash: userHash
        },
        type: "POST"
    });
    return post;
};

The code that you see here is the output from the compiling of LiveScript which we use extensively. 您在这里看到的代码是我们广泛使用的LiveScript编译的输出。 I don't think the LiveScript is having an effect on the final result, I just had to do a lot to get what I expected would be the proper JavaScript / jQuery output. 我不认为LiveScript对最终结果有影响,我只需要做很多工作就可以得到我期望的正确的JavaScript / jQuery输出。

NOTE : because this is more or less the first pass at the code foo doesn't get passed along to the subsequent if statement as userRole was originally hard-coded for the initial testing prior to trying to make the function more dynamic. 注意 :因为这或多或少是代码的第一次传递foo没有传递给后续的if语句,因为在尝试使函数更加动态之前, userRole最初是硬编码的初始测试。

How do I return foo.responseText or bar for use in the subsequent procedure? 如何返回foo.responseTextbar以便在后续过程中使用? Do I need to put the procedure, beginning with the if conditional in the .done() function? 我是否需要在.done()函数中以if条件开头放置过程?

You're looking for .then and not .done . 你在找.then而不是.done

What .done does is perform an action and return the same promise . .done做的是执行一个动作并返回相同的承诺 On the other hand then returns a new promise which is resolved with the return value of the callback provided to it. 另一方面, then返回一个新的promise,它将使用提供给它的回调的返回值来解析。 (Assuming the $.ajax resolved correctly). (假设$.ajax正确解析)。

You of course then need to place everything you subsequently do in the chain: 当然,您需要将随后所做的一切都放在链中:

userRole.then(function(data){
    var bar;
    bar = foo.responseText; // correctly returns the JSON data
    console.log(bar);
    return bar;
}).then(function(role){;
  if (role != false) {
    role = jsonDecode(userRole);
  } else {
    userRole = "";
  }
//...
  return true;
});

You should also return that promise to hook on it later. 您还应该return该承诺以便以后挂钩。

It looks like you are using deferred objects synchronously, which (as you mentioned in your title) is not the intended purpose. 看起来您正在同步使用延迟对象,(正如您在标题中提到的那样)不是预期目的。 The code that you process the user data with after .done() will execute immediately after registering that handler, so your data won't be ready yet. 使用.done()之后处理用户数据的代码将在注册该处理程序后立即执行,因此您的数据尚未准备就绪。

When you register a .then() on a deferred promise, you're telling your program to run a piece of code after the deferred object has either resolved or rejected. 当您在延迟的承诺上注册.then()时,您告诉您的程序在延迟对象已解决或拒绝后运行一段代码。 The program will not wait until that deferred object has resolved or rejected, it will continue processing code (which is the beauty of the deferred object system!) 程序不会等到延迟对象已经解决或拒绝,它将继续处理代码(这是延迟对象系统的美妙!)

Example: 例:

var checkUserRoles = function () {
    var userRole = roleChecker();

    // go off and find the user data
    // but *don't wait for it before continuing code execution*
    userRole.then(function(data){

      // at this point the AJAX request has finished, and we have the data
      console.log(data);

      // put code to process the user data here
    });

    // code here is executed immediately after registering the .then handler
    // so the user data has not loaded yet
};

var roleChecker = function () {
    var defer = $.Deferred();
    var post = defer.promise();

    // simulate an AJAX Request, returns after 2 seconds
    setTimeout(function () {
      defer.resolve('user data here!');   
    }, 2000);

    return post;
};

checkUserRoles();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM