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

时间:2014-12-12 19:30:50

标签: javascript jquery promise deferred

我正在尝试使用jQuery的AJAX延迟来返回一个可以解析和使用的JSON字符串,但是我已将自己编码到一个角落并且可能搞砸了逻辑。我希望在.done()回调中返回AJAX调用的结果,它们是。我曾经想过,我可以返回结果,以便在函数的其余部分中使用。我知道我错过了一些非常明显和简单的东西,我只是不知道它是什么。

这是函数的初始编码,在测试模式下非常多。 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;
};

您在此处看到的代码是我们广泛使用的LiveScript编译的输出。我不认为LiveScript对最终结果有影响,我只需要做很多工作就可以得到我期望的正确的JavaScript / jQuery输出。

注意:因为这或多或少是代码foo的第一次传递,因为userRole最初是硬的,所以不会传递给后续的if语句在尝试使函数更具动态性之前编码进行初始测试。

如何在后续程序中返回foo.responseTextbar?我是否需要在if函数中以.done()条件开头执行该过程?

2 个答案:

答案 0 :(得分:2)

您正在寻找.then而不是.done

.done执行操作并返回相同的承诺。另一方面,then返回一个新的promise,它使用提供给它的回调的返回值来解析。 (假设$.ajax已正确解析)。

当然,您需要将随后所做的一切都放在链中:

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;
});

你也应该return承诺以后挂钩。

答案 1 :(得分:1)

看起来您正在同步使用延迟对象,(正如您在标题中提到的那样)不是预期目的。在.done()之后处理用户数据的代码将在注册该处理程序后立即执行,因此您的数据尚未准备就绪。

当您在延期承诺上注册.then()时,您会告诉您的程序在延迟对象解决或拒绝后运行一段代码。程序不会等待,直到延迟对象解析或拒绝,它将继续处理代码(这是延迟对象系统的美妙!)

示例:

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();