Kept on seeing this pattern in code, but couldn't find any reference to it in google or SO, strange. Can someone point me to reference for this.async() function?
var done = this.async();
// ...
$.get(path, function(contents) { // or some other function with callback
// ...
done(JST[path] = tmpl);
})
Kept on seeing this pattern in code, but couldn't find any reference to it in google or SO, strange. Can someone point me to reference for this.async() function?
var done = this.async();
// ...
$.get(path, function(contents) { // or some other function with callback
// ...
done(JST[path] = tmpl);
})
Share
Improve this question
asked Jun 17, 2012 at 14:42
TonyTony
38.4k10 gold badges53 silver badges83 bronze badges
2
- 8 That's no built-in function. It must be provided by some library/framework. – user123444555621 Commented Jun 17, 2012 at 14:45
- This is a Grunt thing. this.async() is part of their Tasks: gruntjs.com/inside-tasks#inside-all-tasks – Aziel Commented Aug 9, 2019 at 8:54
3 Answers
Reset to default 20var done = this.async()
and done(blah)
is a clever trick to return a value fetched from asynchronous call (e.g. $.get
) within a synchronous function.
Let's see an example:
var getText = function() {
return "hello";
};
var text = getText();
It's a pretty straightforward function call so no puzzle here. However, what if you need to fetch the text asynchronously in getText() function?
var getText = function() {
return $.get('<some-url>', function(text) {
return text;
}); // ??????
};
call to getText()
doesn't return the text you want to get. It returns jquery's promise object.
So how do we make getText()
return the text it gets from $.get()
call?
var getText = function() {
var done = this.async();
$.get('<some-url>', function(text) {
done(text);
});
};
var text = getText(); // you get the expected text
Magic, right?
I don't know the inner-working of this.async()
call yet. I don't know if there is a library provides that function, but you can see that Backbone.LayoutManager uses this trick https://github.com/tbranyen/backbone.layoutmanager/blob/master/backbone.layoutmanager.js (search for this.async).
Also, Tim Branyen (the author of backbone layoutmanager) briefly talks about it in his video tutorial (http://vimeo.com/32765088 around 14:00 - 15:00). In the video, Tim says Ben Alman came up with that trick. Take a look at this as well https://github.com/cowboy/javascript-sync-async-foreach
I think it's a pretty neat trick to mix async and sync functions.
Cheers,
var done = this.async()
is a pattern used in Grunt to help perform asynchronous functions within a Task.
You need to invoke done()
or done(returnValues)
to tell Grunt the task is complete (after your chain of asynchronous tasks).
Read more about it: https://gruntjs.com/inside-tasks#inside-all-tasks
It is a way to work around the problem of this
escaping inside callback. Without this extra reference the code would look like this:
$.get(path, function(contents) { // or some other function with callback
//Wrong! `this` might no longer point to your object
this.done(JST[path] = tmpl);
})
Unfortunately! this
inside response callback is not the same as this
outside of it. In fact it can be anything, depending on what $.get
(calling the callback using) decides it to be. Most of the people use extra reference named that
for the same purpose:
var that = this;
// ...
$.get(path, function(contents) { // or some other function with callback
// ...
that.async(JST[path] = tmpl);
})
This pattern also seems reasonable and readable.
Oh, and if you are curious about this syntax:
done(JST[path] = tmpl)
This is an assignment used as an expression. The value of assignment is the right-hand side, so this code is equivalent to:
JST[path] = tmpl;
done(tmpl);