WEB开发网
开发学院网页设计JavaScript 写个 JavaScript 异步调用框架 (Part 5 - 链式实现... 阅读

写个 JavaScript 异步调用框架 (Part 5 - 链式实现)

 2010-09-14 13:47:46 来源:WEB开发网   
核心提示: 异步队列 如何才能让原本仅支持同步的队列变得也支持异步?这需要检测队列中的每一个调用的返回,如果返回类型为Async.Operation,写个 JavaScript 异步调用框架 (Part 5 - 链式实现)(2),我们知道是异步调用,从而使用特殊的方法等它执行完后再执行下去,在链式调用

异步队列

如何才能让原本仅支持同步的队列变得也支持异步?这需要检测队列中的每一个调用的返回,如果返回类型为Async.Operation,我们知道是异步调用,从而使用特殊的方法等它执行完后再执行下去。

callbackResult = callback(self.result);
self.result = callbackResult;
if (callbackResult && callbackResult instanceof Async.Operation) {
  innerChain = Async.chain();
  while (callbackQueue.length > 0) {
    innerChain.next(callbackQueue.shift());
  }
  innerChain.next(function(result) {
    self.result = result;
    self.state = "completed";
    self.completed = true;
    return result;
  });
  callbackResult.addCallback(function(result) {
    self.result = result;
    innerChain.go(result);
  });
}

如果调用返回了一个Async.Operation实例,我们就利用它自身的addCallback方法帮我们执行队列中余下的调用。准确来说,是我们构造了一个新的调用链,把队列余下的调用都转移到新的调用链上,然后让当前异步调用在回调中启动这个新的调用链。

此外还有一些地方我们需要略作修改,以兼容新的异步调用队列的。例如result、state、completed的状态变更,在链式调用中是有所不同的。

小结

我们在原有的Async.Operation上略作修改,使得它支持异步调用队列,完整的代码看这里:

Async = {};

Async.Operation = function(options) {
    options = options || {};

    var callbackQueue = [];
    var chain = (options.chain && options.chain === true) ? true : false;
    var started = false;
    var innerChain = null;
   
    this.result = undefined;
    this.state = "running";
    this.completed = false;
   
    this.yield = function(result) {
        var self = this;
       
        if (!chain) {
            self.result = result;
            self.state = "completed";
            self.completed = true;
        } else {
            started = true;
            self.result = result;
            self.state = "chain running";
            self.completed = false;
        }

        setTimeout(function() {
            if (!innerChain) {
                while (callbackQueue.length > 0) {
                    var callback = callbackQueue.shift();
                    if (chain) {
                        callbackResult = callback(self.result);
                        self.result = callbackResult;
                        if (callbackResult && callbackResult instanceof Async.Operation) {
                            innerChain = Async.chain();
                            while (callbackQueue.length > 0) {
                                innerChain.next(callbackQueue.shift());
                            }
                            innerChain.next(function(result) {
                                self.result = result;
                                self.state = "completed";
                                self.completed = true;
                                return result;
                            });
                            callbackResult.addCallback(function(result) {
                                self.result = result;
                                innerChain.go(result);
                            });
                        }
                    } else {
                        callback(self.result);
                    }
                }

                if (!innerChain) {
                    self.state = "completed";
                    self.completed = true;
                }
            } else {
                while (callbackQueue.length > 0) {
                    innerChain.next(callbackQueue.shift());
                }
                innerChain.next(function(result) {
                    self.result = result;
                    self.state = "completed";
                    self.completed = true;
                    return result;
                });
            }
        }, 1);
        return this;
    };

    this.go = function(initialArgument) {
        return this.yield(initialArgument);
    }

    this.addCallback = function(callback) {
        callbackQueue.push(callback);
        if (this.completed || (chain && started)) {
            this.yield(this.result);
        }
        return this;
    };

    this.next = function(nextFunction) {
        return this.addCallback(nextFunction);
    };
};

Async.chain = function(firstFunction) {
    var chain = new Async.Operation({ chain: true });
    if (firstFunction) {
        chain.next(firstFunction);
    }
    return chain;
};

Async.go = function(initialArgument) {
    return Async.chain().go(initialArgument);
}

上一页  1 2 

Tags:JavaScript 异步 调用

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接