How to use promises, or complete an ajax request before the function finishes?
As per the documentation you dont need to wrap the ajax with a promise which already implements promise. Instead chain the response as explained below.
The jqXHR objects returned by $.ajax() as of jQuery 1.5 implement the Promise interface, giving them all the properties, methods, and behavior of a Promise (see Deferred object for more information)
You can do something like below by chaining the response:
function isStaff(url, post) {
return $.ajax({
url: url,
dataType:"json"
}).then(function(resp){
//resp = $.parseJSON(resp); /*You dont require this if you have respose as JSON object. Just Specify it in 'dataType'*/
var source = $('#feed-item-template').html();
var template = Handlebars.compile(source);
var context = {
id: post.id,
content: post.text,
author: post.author,
date: $.timeago(post.date),
staff: resp.is_staff === 1 ? true : false
};
return template(context);
});
}
isStaff(url, post).done(function(template){
/*Your compiled template code is available here*/
}).fail(function(jqXHR, textStatus, errorThrown){
console.log("Error:"+textStatus);
});
Note: Be sure to implement error callbacks also. Because you may never know what went wrong :)
Simple explanation about promise with $.defer:
For understanding i have created the Fiddle similar to your requirement.
Explanation:
Basically Promise is been introduced to attain synchronous execution of asynchronous JS code.
What do you mean by Async or Asynchronous code?
The code that is executed may return a value at any given point of time which is not immediate. Famous example to support this statement would be jquery ajax
.
Why is it required?
Promise implementations helps a developer to implement a synchronous code block which depends on asynchronous code block for response,. like in ajax call when i make a request to server asking for a data string, i need to wait till the server responds back to me with a response data string which my synchronous code uses it to manipulate it , do some logic and update the UI.
Follow this link where the author has explained with detailed examples.
PS: Jquery $.defer
implements or wraps promise
in quite a different way. Both are used for the same purpose.
First, let's simplify the compilePost
function. This function should know how to compile a post in a synchronous manner. Let's change the isStaff
fetching to a simple argument.
function compilePost(post, isStaff) {
var source = $('#feed-item-template').html();
var template = Handlebars.compile(source);
var context = {
id: post.id,
content: post.text,
author: post.author,
date: $.timeago(post.date),
staff: isStaff
}
var html= template(context);
return html;
}
Now, let's create a new method, with a single purpose - checking if a user is member of the staff:
function checkForStaffMemebership() {
return new Promise(function (resolve, reject) {
$.ajax({
url: url,
success: function (data) {
var session = $.parseJSON(data);
if (session.is_staff === 1) {
resolve(true);
} else {
resolve(false);
}
}
});
});
}
This function wraps your original ajax
call to the server with a promise, whenever the $.ajax
call gets a response from the server, the promise will resolve with the answer whether the user is a staff member or not.
Now, we can write another function to orchestrate the process:
function compilePostAsync(post) {
return checkForStaffMemebership()
.then(function (isStaff) {
return compilePost(post, isStaff);
});
}
compilePostAsync
finds out whether the user is a staff member or not. Then, it's compiling the post.
Please notice that compilePostAsync
returns a promise, and thus if you used to have something like:
element.innerHTML = compilePost(post);
Now, you should change it to something like:
compilePostAsync(post).then(function (compiledPost) {
element.innerHTML = compiledPost;
});
Some notes:
- This is only an example, it surely misses some things (proper error handling for example)
- The
isStaff
andcheckForStaffMemebership
(original and new) do not get any argument, I guess you'd figure out how to pass the userId or any other data you might need - Read about promises, it's a useful tool to have, there is a lot of data about it on the web, for example: MDN.