Reputation: 564
I am trying to figure out the logic required for promises to work. My (simplified) example does this:
var FLEX = FLEX || {};
FLEX.Core = {
__networkIdToken: '',
__r: "",
Init: function() {
var deferred = $.Deferred();
FLEX.Core.Config();
FLEX.Core.RegisterHandlers();
FLEX.Core.Execute();
},
Config: function() {
yam.config({
debug: true,
appId: FLEX_YAMMER_CONFIGID
});
},
RegisterHandlers: function() {
$(FLEX_YAMMER_LOGINBUTTON).on('click', function(){
FLEX.Core.Login();
});
},
Execute: function() {
//Get Network Token from local storage (if exists)
__networkIdToken = localStorage.getItem(FLEX_YAMMER_AUTHTOKEN);
if(__networkIdToken != null)
{
//If network token is set then set Auth Token and continue
yam.platform.setAuthToken(__networkIdToken);
//RETURN NEEDS TO HAPPEN HERE
}
else
{
//If no Network Token set, display login panel to enable login
FLEX.Core.ShowLoginPanel(false);
}
},
ShowLoginPanel: function (_loggedIn) {
if (_loggedIn) {
$(FLEX_YAMMER_LOGINPANEL).hide();
} else {
$(FLEX_YAMMER_LOGINPANEL).show();
}
}
}
$(document).ready(function () {
FLEX.Core.Init().done(testFunction);
function testFunction()
{
alert('Test');
}
});
The Call from document ready needs to check if the user is logged in. (execute function). If the local storage object (which sets __networkIdToken) is empty then it will show the login panel and this has independent button logic (removed from example). If there IS a network id then i would like a promise to be returned here...removed the need to any async logic for login.
Thanks
Upvotes: 0
Views: 184
Reputation: 665536
__r = $.Deferred(); […] return __r;
__r
is a property of your object, but here you're assigning to a global variable! Change to
this.__r = …
[…]
return this.__r;
FLEX.Login(); }
You're not returning anything from the INIT
method on which the .done()
could be called. (Also, you're missing .Core
in the access of .Login
) Change it to
return this.Login();
}
Design Pattern improvement: Every function that does any asynchronous tasks should create an Deferred itself, and return
a Promise for it.
with a final function which i was hoping to return the deferred object
No, that's not how promises work. The initial function handles the deferred and returns the promise, the "final" (asynchronous callback) function only resolves the deferred - which might trigger other processes (the "final" is local to one async task, not "final" handler in a chain of tasks).
var FLEX = FLEX || {};
FLEX.Core = {
__networkIdToken: '',
__r: null,
Init: function() {
// some pseudo-action that might resemble your process
// implemented with promises
this.__r = FLEX.getAuthToken().catch(function(noAuthTokenError) {
showLoginForm();
return getNextFormSubmission().then(function(credentials) {
return serverRequest(credentials).then(function (token) {
hideLoginForm();
return token;
}, function(authError) {
// try again? Get next form submission...
});
});
}).then(function(token) {
yam.platform.setAuthToken(token);
});
return this.__r;
},
Login: function () {
var d = $.Deferred();
//Asynchronous Login Code Goes here, callback {
d.resolve();
// or
d.reject();
// }
return d.promise();
}
// similarly for the other async tasks
}
If there IS a network id then i would like a promise to be returned here...removed the need to any async logic for login
You always want to return a promise, even if the result is synchronously available. The logic to handle a maybe-async login must be asynchronous anyway. In your case, it might look like
FLEX.getAuthToken /* as used above */ = function() {
var __networkIdToken = localStorage.getItem(FLEX_YAMMER_AUTHTOKEN);
if (__networkIdToken != null)
return $.when(__networkIdToken);
else
return $.Deferred().reject(); // the rejection will be handled by the .catch
// or maybe try another storage?
}
Upvotes: 1