简体   繁体   中英

How to realize a chain in JS?

I know that we can use "return this" in object, eg:

var $ = {
   name : function(){
     alert("John");
     return this;
  },
  age  : function(){
     alert(21);
     return this
  }
}

$.name().age()

When one function is completed next one will be called. But in JQuery there is such construction:

 $.get(url).done(callback).fail(callback);

How it works? How: method "get" gets callback on time. Ajax request is async by default.

PS I am interested in realization without $.Defferred object.

Thanks.

Here's how $.get(url).done(callback); works.

$.get() returns an object. It returns that object immediately as soon as the async ajax call has been started (it does not wait until the ajax calls finishes). That object has a number of methods which includes the jQuery promise methods. One of those methods is .done() . When you call .done(callback) on that returned object it stores the callback in a list of callbacks in that returned object.

When the $.get() function finishes sometime later, it then .resolves() it's own promise which ends up looking for all the .done() callbacks stored in the object and calls the callbacks one at a time.

So, in this sequence of events, .done() is actually called immediately right after $.ajax() finishes initiating the ajax call, but all .done() does when it executes is store the callback for use later by $.ajax() when the async operation finishes.

Whether you know it or not, when you use the $.get(url).done(callback) construction, you are using a jQuery promise object and the promise API. It works pretty simply here because $.get() creates the promise object for you (and returns it and will then .resolve() or .fail() it later) and all you have to do is specify .done() , .fail() or .then() callbacks and most of the work is done for you. You don't have to manually create a deferred object or promise object - you can just use the one returned by the ajax call.


Here's a little async queue that supports chaining for visual effects with it's own .done() handler: http://jsfiddle.net/jfriend00/tS8G3/

function domWrapper(elem) {
    if (!(this instanceof domWrapper)) {
        return new domWrapper(elem);
    }
    if (typeof elem === "string") {
        elem = document.getElementById(elem);
    }
    this.elem = elem;
    this.q = [];
    this.timer = null;
    this.doneCallbacks = [];
}

domWrapper.prototype = {
    hide: function() {
        this.q.push({op: "hide"});
        this._exec();
        return this;
    },
    show: function() {
        this.q.push({op: "show"});
        this._exec();
        return this;
    },
    delay: function(t) {
        this.q.push({op: "delay", time: t});
        this._exec();
        return this;
    },
    done: function(fn) {
        this.doneCallbacks.push(fn);
        return this;
    },
    _exec: function() {
        var next;
        while (!this.timer && this.q.length) {
            next = this.q.shift();
            switch(next.op) {
                case "show":
                    this.elem.style.display = "block";
                    break;
                case "hide":
                    this.elem.style.display = "none";
                    break;
                case "delay":
                    var self = this;
                    this.timer = setTimeout(function() {
                        self.timer = null;
                        self._exec();
                    }, next.time);
                    break;
            }
        }
        // if all done with all pending activities
        if (!this.q.length && !this.timer) {
            // call the done callbacks
            for (var i = 0; i < this.doneCallbacks.length; i++) {
                this.doneCallbacks[i].call(this.elem);
            }
        }
    }
}

function makeBlue() {
    this.style.backgroundColor = "blue";
}

function makeBigger() {
    this.style.width = "200px";

}

domWrapper("test").done(makeBlue).done(makeBigger)
    .delay(2000).hide().delay(2000).show().delay(1000);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM