使用jQuery $ .get()的骨干路由器承诺确定用户未按预期工作的登录状态

时间:2014-02-02 06:26:57

标签: javascript jquery backbone.js

我正在尝试使用jQuery承诺让authenticated.done等到$.get()中的.isAuthenticated返回,但我没有得到我期待的结果...... authenticated.done内的函数在前面的$.get()返回之前运行,因此不起作用。我做错了什么,或者我是以完全错误的方式解决这个问题?

isAuthenticated : function() {
    // make a request to the server and see if the response is a login form or not
    // this should just return true or false, not actually handle login etc
    var authenticated = false;
    console.log("authenticating...");

    var ready = Promise.from(null);

    $.get("/loggedin")
    .then(function(data, textStatus) {
        var rtnVal = false;
        if (textStatus == "success" && !(data instanceof Object)) {
            console.log("failure returned");
        } else {
            console.log("success returned");
            rtnVal = true;
        }
        return rtnVal;
    })
    .done(function(result) {
        authenticated = result;
    });

    return ready.then(function () {
        return authenticated;
    })
},

render: function (view) {

    if(this.currentView) this.currentView.destroy();

    var authenticated = this.isAuthenticated();

    authenticated.done(function (response) {
        if (response == true) {
            console.log("Authentication success!");
            // set the currentView
            this.currentView = view;

            // render the new view
            this.currentView.render();

            // set the view's menu items
            if (this.currentView.navLink !== undefined) {
                $(this.currentView.navLink).addClass("active");
            }
        } else {
            console.log("Authentication failed...");
            view = new app.LoginView();
            view.render();
            this.currentView = view;
        }
    });

    return this;
}

控制台输出:

authenticating... router.js:45
Authentication failed... router.js:89
success returned router.js:55

2 个答案:

答案 0 :(得分:2)

以下是使用jQuery的Deferred / Promise对象的代码:

{
    authenticate: function () {
        var authentication = $.Deferred();

        $.get("/loggedin")
        .then(function (data, textStatus) {
            if (textStatus === "success" && !(data instanceof Object)) {
                authentication.resolve(data, textStatus);
            } else {
                authentication.reject(data, textStatus);
            }
        });
        return authentication.promise();
    },
    render: function (view) {
        if (this.currentView) this.currentView.destroy();

        this.authenticate()
        .done(function (data, textStatus) {
            this.currentView = view;
            this.currentView.render();
            $(this.currentView.navLink).addClass("active");
        })
        .fail(function (data, textStatus) {
            view = new app.LoginView();
            view.render();
            this.currentView = view;
        });
        return this;
    }
};

注意:

  • 因为无论GET请求成功与否,都会调用then,因此您不需要fail回调。
  • 我已将该功能重命名为更合适的authenticate,因为它是一个动作,而不是一个州
  • jQuery不关心您是否将undefined传递给它,因此您的if (this.currentView.navLink !== undefined)支票是多余的
  • 您可能希望以某种方式在身份验证回调中使用datatextStatus。如果您不需要它们,请在不带参数的情况下致电resolve()reject()

答案 1 :(得分:0)

我不知道您正在使用的Promise对象是什么,但使用标准的jquery延迟对象代码将会显示:

isAuthenticated : function() {
    // make a request to the server and see if the response is a login form or not
    // this should just return true or false, not actually handle login etc
    var authenticated = $.Deferred();
    console.log("authenticating...");

    $.get("/loggedin")
    .then(function(data, textStatus) {
        if (textStatus == "success" && !(data instanceof Object)) {
            console.log("failure returned");
            authenticated.reject();
        } else {
            console.log("success returned");
            authenticated.resolve();
        }
    }, function () {
        authenticated.reject();
    });

    return authenticated;
},

render: function (view) {

    if(this.currentView) this.currentView.destroy();

    var authenticated = this.isAuthenticated();

    authenticated.done(function (response) {
        if (response == true) {
            console.log("Authentication success!");
            // set the currentView
            this.currentView = view;

            // render the new view
            this.currentView.render();

            // set the view's menu items
            if (this.currentView.navLink !== undefined) {
                $(this.currentView.navLink).addClass("active");
            }
        } else {
            console.log("Authentication failed...");
            view = new app.LoginView();
            view.render();
            this.currentView = view;
        }
    });

    authenticated.fail(function () {console.log('failed')});

    return this;
}