Deferreds
How to use deferreds to attach an unknown number of possibly asynchronous functions to a save button.
by nate
HTML
<p>This is a save button. There is an unknown number of things on the page that need to run functions on click but before the final save event.</p>
<button>Save</button>
<div></div>
CSS
body {
color: #666;
font-family: Helvetica, sans-serif;
padding: 25px;
}
p {
margin-bottom: 1em;
}
button {
margin-bottom: 1em;
}
p:last-child {
color: red;
}
JavaScript
// This is a first-draft model for a hooks pattern for saving
// that accomodates both synchronous and asynchronous functions
// Questions:
// Does this way of adding functions to the hooks array make sense?
// Is there a way we could make it simpler?
var $div = $('div'),
hooks = [];
/* Run all the functions in the hooks array, then save */
$('button').on('click', function (event) {
$.when.apply($, $.map(hooks, function (hook) { return hook(); })).done(function () {
$div.append('<p>All hooked functions have finished.\nNOW we can save.</p>');
});
});
// Add an AJAX call to the hooks
// AJAX calls have built-in support for deffereds
hooks.push(function () {
return $.post('/echo/html/', {
html: "<p>AJAX task #1 complete.</p>",
delay: 1
}).success(function(data) {
$("div").append(data);
});
});
// Add an AJAX call to the hooks
hooks.push(function () {
return $.post('/echo/html/', {
html: "<p>AJAX task #2 complete.</p>",
delay: 2
}).success(function(data) {
$("div").append(data);
});
});
// Add an AJAX call to the hooks
hooks.push(function () {
return $.post('/echo/html/', {
html: "<p>AJAX task #3 complete.</p>",
delay: 3
}).success(function(data) {
$("div").append(data);
});
});
// Add an AJAX call to the hooks
hooks.push(function () {
return $.post('/echo/html/', {
html: "<p>AJAX task #4 complete.</p>",
delay: 4
}).success(function(data) {
$("div").append(data);
});
});
// Add a regular ol' function to the hooks
hooks.push(function () {
$div.append('<p>I\'m just a regular function. I am not asynchronous.</p>');
});
// Add a non-AJAX function that might take some time...
// it uses a custom deferred
hooks.push(function () {
var dfd = $.Deferred();
$div.append('<p>I\'m a custom function that needs a deferred. It might take six seconds.</p>');
setTimeout(function () {
...