开发者

How do I call a function as a parameter at the end of a jQuery command chain?

...if the last command do开发者_StackOverflow社区esnt have a callback function? Like for example

$(something).remove(other_thing).append(new_thing)

Append doesnt have a callback function, so my question is, is there a jQuery method (or other way) to call a passed function after a chain of commands? The function doesnt have to affect the current selection.

EDIT: I know the methods in this example shouldnt take long so a callback wouldnt be necessary, but that was just the first example I could think of. so please think of it as if this wasnt the case


Given the fact that append is done very quickly, there's no need for it to have a callback. If you want to call another function, just do it on the next line.

$(something).remove(other_thing).append(new_thing);
yourFunction();

Update

Some functions are synchronous and some are asynchronous. When an asynchronous function, like $.ajax, executes, javascript immediately executes the next line of code whether the asynchronous function has completed or not. Synchronous functions, on the other hand block javascript from executing any other code until it completes. The reason that asynchronous functions accept a callback is to execute code that must wait for the asynchronous function to complete before it's run. Functions that don't accept a callback are synchronous, and are intentionally blocking or don't expect to be long running.

Synchronous versus asynchronous calls


To expand on Craig's answer, you simply invoke your function normally in the next statement.

The purpose of a callback function is so that you can do something after something else—which will take an indeterminate amount of time, like a network (AJAX) call—completes. Key to this is that the other operation does not block. In other words, it happens—or, from your script's perspective, appears to happen—on another thread.

Consider how an AJAX call works.

var d;
$.get('/something', function(r) {
    // this is a callback function
    d = r;
    alert(d);
});
// this is the next statement
console.log(d);

The call to $.get 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 /something, and eventually receives a response. These things happen in the background while your script continues to execute.

The call to console.log executes after the call to $.get returns. Since $.get returns immediately, the log call happens before the browser has even had a chance to connect to the server. This means d will be undefined, and your call to console.log will just show "undefined".

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 d, and the call to alert has your data. Magic!

Now consider how jQuery's DOM manipulation functions (like append) work. They are synchronous. That means that your call to append blocks—and your script can do nothing else—until the function has completed all of its work.

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.

Thus, it is not useful for jQuery to provide callback functions on DOM manipulation methods (or any other synchronous method).

Here's what append looks like from a vastly simplified standpoint:

$.fn.append = function(elem) {
    // do stuff, specifically
    this.appendChild(elem);
};

Here's what it would look like if we added the option to have a callback:

$.fn.append = function(elem, callback) {
    // do stuff, specifically
    this.appendChild(elem);
    if (callback) callback();
};

And now, what you would do from your code, respectively:

$('#something').append('<b>Foo</b>');
addBar();
console.log('Done');

$('#something').append('<b>Foo</b>', function() {
    addBar();
});
console.log('Done');

These two snippets are guaranteed to execute exactly the same, every time.

  1. You call .append. jQuery works some if its magic, and eventually calls the native appendChild on #something.
  2. appendChild appends the new node(s) to #something. 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.
  3. Control returns from appendChild.
  4. What happens next depends on which 'version' we're talking about.
    • In the normal version:
      1. Control returns from .append().
      2. The next statement of your script executes. In this case, we call addBar().
      3. When addBar is done, the next statement, console.log('Done') is called.
    • In the callback version:
      1. .append() checks if you've supplied a callback, and you have, so...
      2. .append() calls the callback function.
      3. In the callback, we call addBar().
      4. When addBar is done, control returns to the callback function, and since there's nothing else in the function, it returns as well.
      5. Control has now returned to .append(), and there is nothing left to execute in that function, so control returns from .append().
      6. The next statement of your script executes. console.log('Done') is called.

As you can see, no matter which way we do it,

  1. The element is appended to the DOM.
  2. addBar() is called.
  3. console.log() is called.

As a rule: If a jQuery function does not provide the option to pass a callback, the function is synchronous, and therefore you can just proceed with your next step on the next line.


Edit: If you want to call a function in the middle of a chain, jQuery doesn't provide anything built-in, but we can write our own plugin!

jQuery.fn.invoke = function() {
    var args = Array.prototype.slice.call(arguments), fn = args.shift();
    fn.apply(this, args);
    return this;
};

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, this refers to the jQuery object from your chain. The function's return value is ignored. Demo.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜