jQuery Deferred не работает должным образом

Это мой первый раз, когда я использую $.Deferred();, и это оказалось миссией.

Я прочитал jQuery Deferred не работает, но это относится к событиям ajax, так что на самом деле это не так. помогите в моем случае.

У меня есть следующий код в javascript:

var deferred = $.Deferred();

deferred.done(function() {
    console.log(auth.loggedIn);
    if(auth.loggedIn) {
        app.page = 'usr/dashboard';
    }
}

deferred.resolve(auth.initialize());

Мой объект auth выглядит так:

var auth = {

    loggedIn:false,

    initialize:function() {
        var data = {
            'login_token':app.getCookie('login_token'),
            'usr_id':app.getCookie('usr_id'),
            'source':config.source,
            'language_code':config.language_code,
            'country_code':config.country_code
        }
        app.api('usr/loggedin',data,function(data) {
            var response = JSON.parse(data);
            if(!response.result) {
                auth.loggedIn = false;
            }
            auth.loggedIn = true;
            console.log(auth.loggedIn);
        },'post');
    }
}

Теперь, если я console.log(response) в обратном вызове app.api, ответ будет именно таким, каким я его ожидаю, если я console.log(auth.loggedIn) получу true.

Если я console.log в deferred.done и console.log(auth.loggedIn)initialize я получаю два разных значения. Что я делаю неправильно и как я могу заставить свое приложение ждать установки auth.loggedIn?

ОБНОВИТЬ

Вот как я сейчас это делаю в своем основном файле:

auth.initialize().done(function(auth) {
    if(auth.loggedIn) {
        app.page = 'usr/dashboard';
    }
    jsRouter.initialize();
});

jsRouter основан на этом 20-строчном маршрутизаторе JavaScript и теперь только иногда показывает страницу шаблона, независимо от того, на какой странице я нахожусь.

Функция jsRouter.initialize выглядит так:

initialize:function() {
    window.addEventListener('hashchange',jsRouter.router);
    window.addEventListener('load',jsRouter.router);

    /* ERROR PAGES */
    jsRouter.route('404','errors/404',function() {});
    jsRouter.route('500','errors/500',function() {});

    /* ACTUAL PAGES */
    jsRouter.route('/','home',function() {});
    jsRouter.route('/home','home',function() {});
    jsRouter.route('/usr/register','usr/register',function() {});
    jsRouter.route('/usr/login','usr/login',function() {});
    jsRouter.route('/usr/forgotpassword','usr/forgotpassword',function() {});
    jsRouter.route('/usr/activate','usr/activate',function() {});
    jsRouter.route('/usr/dashboard','usr/dashboard',function() {});
    jsRouter.route('/adr','adr/index',function() {});
},

Я обновил свой обратный вызов app.api, чтобы он выглядел точно так же, как Felix King предложил.


person Bird87 ZA    schedule 07.07.2015    source источник
comment
Я думаю, что вы делаете отсрочку в своем вызове app.api, предполагая, что это вызов AJAX.   -  person Marcos Pérez Gude    schedule 07.07.2015
comment
Кажется, что вы должны return получить результат вызова app.api, но это не так, что приводит к разрешению промиса с неопределенной полезной нагрузкой.   -  person Jon    schedule 07.07.2015
comment
app.api выглядит так, как будто это асинхронный Javascript... не так ли?   -  person Jaromanda X    schedule 07.07.2015
comment
app.api — это функция, которая использует ajax для вызовов API.   -  person Bird87 ZA    schedule 07.07.2015


Ответы (1)


В настоящее время вы разрешаете отложенный объект с помощью undefined, что не имеет смысла. Вы также разрешаете это до того, как был выполнен обратный вызов app.api. Отложенный объект должен быть разрешен асинхронным обратным вызовом.

auth.initialize должен вернуть отложенный объект/обещание, и вы должны разрешить его в обратном вызове app.api:

var auth = {

    loggedIn:false,

    initialize:function() {
       var deferred = new $.Deferred();          // <- create deferred object
        var data = {
            'login_token':app.getCookie('login_token'),
            'usr_id':app.getCookie('usr_id'),
            'source':config.source,
            'language_code':config.language_code,
            'country_code':config.country_code
        }
        app.api('usr/loggedin',data,function(data) {
            auth.loggedIn = JSON.parse(data).result;
            deferred.resolve(auth);              // <- resolve when response was received
        },'post');
        return deferred.promise();               // <- return promise
    }
}

auth.initilize().done(function(auth) { 
  // at this point the login succeeded (or failed)
});
person Felix Kling    schedule 07.07.2015
comment
Только что написал тот же ответ. - person Etheryte; 07.07.2015
comment
Теперь мой маршрутизатор на основе joakimbeng.eu01.aws .af.cm/a-javascript-router-in-20-lines и вызываемый после if(auth.loggedIn) {} только иногда показывает страницу шаблона. - person Bird87 ZA; 07.07.2015
comment
Обновлен мой вопрос, чтобы сделать его более понятным после этого ответа - person Bird87 ZA; 07.07.2015
comment
Это jQuery, поэтому return deferred.promise(); (это метод, а не свойство). - person Roamer-1888; 07.07.2015
comment
@Roamer-1888: Спасибо. Больше не был уверен. Фиксированный. - person Felix Kling; 07.07.2015
comment
Это очень сбивает с толку, особенно если вы переключаетесь между Q и jQuery. Кроме того, не должно ли быть auth.loggedIn = true; в предложении else или что-то более лаконичное? - person Roamer-1888; 07.07.2015
comment
@ Roamer-1888: Верно, тоже исправлено. На логику особо внимания не обращал. - person Felix Kling; 07.07.2015
comment
Ответил очень помог. Спасибо. Решил мою проблему с маршрутизатором, просто позвонив ему перед выполнением аутентификации. - person Bird87 ZA; 08.07.2015