Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>To expand on Craig's answer, you simply invoke your function normally in the next statement.</p> <p>The purpose of a callback function is so that you can do something after something else&mdash;which will take an indeterminate amount of time, like a network (AJAX) call&mdash;completes. Key to this is that the other operation <em>does not block</em>. In other words, it happens&mdash;or, from your script's perspective, appears to happen&mdash;on another thread.</p> <p>Consider how an AJAX call works.</p> <pre><code>var d; $.get('/something', function(r) { // this is a callback function d = r; alert(d); }); // this is the next statement console.log(d); </code></pre> <p>The call to <code>$.get</code> executes first in this program. The first parameter is the URL you want to fetch; the second is an anonymous callback. It will be executed after the browser connects to the server, requests <code>/something</code>, and eventually receives a response. These things happen in the background while your script continues to execute.</p> <p>The call to <code>console.log</code> executes after the call to <code>$.get</code> returns. Since <code>$.get</code> returns <em>immediately</em>, the log call happens before the browser has even had a chance to connect to the server. This means <code>d</code> will be <em>undefined</em>, and your call to <code>console.log</code> will just show "undefined".</p> <p>This is where the usefulness of a callback comes in to play. When the background request completes, the browser fires an event on the XHR object that jQuery used to issue your request. jQuery then calls your callback function with the result of the request. In this function, we now have the data, can set <code>d</code>, and the call to <code>alert</code> has your data. Magic!</p> <p>Now consider how jQuery's DOM manipulation functions (like <code>append</code>) work. <strong>They are synchronous.</strong> That means that your call to <code>append</code> <strong>blocks</strong>&mdash;and your script can do nothing else&mdash;until the function has completed all of its work.</p> <p>This is a consequence of how the browser's native DOM manipulation functions work. They don't return until the change to the DOM is complete.</p> <p>Thus, it is not useful for jQuery to provide callback functions on DOM manipulation methods (or any other synchronous method).</p> <p>Here's what <a href="https://github.com/jquery/jquery/blob/1.6.4/src/manipulation.js#L114" rel="nofollow"><code>append</code></a> looks like from a vastly simplified standpoint:</p> <pre><code>$.fn.append = function(elem) { // do stuff, specifically this.appendChild(elem); }; </code></pre> <p>Here's what it would look like if we added the option to have a callback:</p> <pre><code>$.fn.append = function(elem, callback) { // do stuff, specifically this.appendChild(elem); if (callback) callback(); }; </code></pre> <p>And now, what you would do from your code, respectively:</p> <pre><code>$('#something').append('&lt;b&gt;Foo&lt;/b&gt;'); addBar(); console.log('Done'); </code></pre> <p>&#8203;</p> <pre><code>$('#something').append('&lt;b&gt;Foo&lt;/b&gt;', function() { addBar(); }); console.log('Done'); </code></pre> <p>These two snippets are guaranteed to execute exactly the same, every time.</p> <ol> <li>You call <code>.append</code>. jQuery works some if its magic, and eventually calls the native <code>appendChild</code> on <code>#something</code>.</li> <li><code>appendChild</code> appends the new node(s) to <code>#something</code>. The DOM is modified, and internal data structures are updated to reflect the changes. If you are appending many nodes, this might take a while.</li> <li>Control returns from <code>appendChild</code>.</li> <li>What happens next depends on which 'version' we're talking about. <ul> <li>In the normal version: <ol> <li>Control returns from <code>.append()</code>.</li> <li>The next statement of your script executes. In this case, we call <code>addBar()</code>.</li> <li>When <code>addBar</code> is done, the next statement, <code>console.log('Done')</code> is called.</li> </ol></li> <li>In the callback version: <ol> <li><code>.append()</code> checks if you've supplied a callback, and you have, so...</li> <li><code>.append()</code> calls the callback function.</li> <li>In the callback, we call <code>addBar().</code></li> <li>When <code>addBar</code> is done, control returns to the callback function, and since there's nothing else in the function, it returns as well.</li> <li>Control has now returned to <code>.append()</code>, and there is nothing left to execute in that function, so control returns from <code>.append()</code>.</li> <li>The next statement of your script executes. <code>console.log('Done')</code> is called.</li> </ol></li> </ul></li> </ol> <p>As you can see, no matter which way we do it,</p> <ol> <li>The element is appended to the DOM.</li> <li><code>addBar()</code> is called.</li> <li><code>console.log()</code> is called.</li> </ol> <p>As a rule: <strong>If a jQuery function does not provide the option to pass a callback, the function is synchronous</strong>, and therefore you can just proceed with your next step on the next line.</p> <hr> <p><strong>Edit:</strong> If you want to call a function in the middle of a chain, jQuery doesn't provide anything built-in, but we can write <a href="http://jsfiddle.net/josh3736/SrxX6/" rel="nofollow">our own plugin</a>!</p> <pre><code>jQuery.fn.invoke = function() { var args = Array.prototype.slice.call(arguments), fn = args.shift(); fn.apply(this, args); return this; }; </code></pre> <p>This takes the function you want to call as the first argument, then passes the rest of the arguments to that function. Within the function, <code>this</code> refers to the jQuery object from your chain. The function's return value is ignored. <a href="http://jsfiddle.net/josh3736/SrxX6/" rel="nofollow">Demo.</a></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload