This is my first time using $.Deferred();
and it's proving to be a mission.
I have read jQuery Deferred not working, but that applies to ajax events, so doesn't really help in my case.
I have the following code in javascript:
var deferred = $.Deferred();
deferred.done(function() {
console.log(auth.loggedIn);
if(auth.loggedIn) {
app.page = 'usr/dashboard';
}
}
deferred.resolve(auth.initialize());
My auth
object looks like this:
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');
}
}
Now, if I console.log(response)
in the app.api
callback, the response is exactly what I expect it to be, if I console.log(auth.loggedIn)
I get true
.
If I console.log
in deferred.done
and console.log(auth.loggedIn)
(in initialize
I get two different values. What am I doing wrong and how can I make my app wait for auth.loggedIn
to be set?
This is how I am now doing it in my main file:
auth.initialize().done(function(auth) {
if(auth.loggedIn) {
app.page = 'usr/dashboard';
}
jsRouter.initialize();
});
jsRouter is based on this 20 line javascript router and now only sometimes shows the template page, regardless of the page I am on.
The jsRouter.initialize
function looks like this:
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() {});
},
I have updated my app.api
callback to look exactly like what Felix King suggested.
You are currently resolving the deferred object with undefined
, which does not make sense. You are also resolving it before the app.api
callback was executed.
The deferred object has to be resolved by the asynchronous callback.
auth.initialize
should return the deferred object / promise, and you have to resolve it in the app.api
callback:
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)
});