在javascript中具有常见回调的类

时间:2015-02-05 10:57:03

标签: javascript ajax angularjs callback

我想构建一个 javascript类来注册几个不同的函数来执行一个公共回调,所有注册的函数都应该执行异步,然后一旦完成所有这些就完成了,它应该执行定义的回调函数

我们还应该能够在回调函数执行之前定义最长时间。例如,如果我们将其定义为 3000 并且所有已注册函数返回的时间超过 3000 ms ,则应该继续执行回调函数,即使ajax函数没有完成了重新调整。

需要明确的是,此代码需要灵活,独立且可重复使用

假设我们注册的任何函数将实现对我们在其中某个点定义的函数的调用,标记其完成。例如。在我的函数结束时,我将输入 myClass.markDone()让该类知道函数已完成执行

是否可以使用javascript或angular.js而不使用jquery?

3 个答案:

答案 0 :(得分:1)

要实现这一目标,请查看这些内置角度模块:

https://docs.angularjs.org/api/ng/service/ $ Q

https://docs.angularjs.org/api/ng/service/ $超时

以下是plunkr的示例实现:

qAllWithTimeout([
    makePromise(function(callback) {
      // Mock async call 1
      setTimeout(callback, 200);
    }),
    makePromise(function(callback) {
      // Mock async call 2
      setTimeout(callback, 500);
    }),
    makePromise(function(callback) {
      // Long running mock async call 2
      setTimeout(callback, 10500);
    })
  ], 3000)
    .then(function() {        
        $scope.state = 'ready';
    })

http://plnkr.co/edit/hNo9kJmKIR4hEoNk9pP2?p=preview

答案 1 :(得分:0)

我不确定这会起作用,我没有经过测试。这可能会给你一些想法。

function TestFun(callback, timeout){
    this._callback = callback;
    this._timeout = timeout;
    this._forceFinish = false;
    this.fun_list = [];
    this.RegisterFun = function(fun){
        this.fun_list.push(fun);
    };

    this.startCount = -1;
    this.finishCount = 0;

    this.timeOutFunction= function(){
        this.startCount++;
        fun_list[this.startCount]();
        this.commonCallback();
    }
    this.Start = function(){
        for(var i=0; i <this.fun_list.length ;i++){
            setTimeout( this.timeOutFunction, 0);
        }
        setTimeout( this.watcherFun, 1 );
    };

    this.commonCallback = function(){
        if( this._forceFinish){
            this._callback();
        }else{
            this.finishCount++;
            if(this.finishCount == this.fun_list.length ){
                this._callback();
            }
        }
    }

    this.watcherFun = function(){
        if( this._timeout !=0 ){
            this._timeout-1;
            setTimeout( this.watcherFun, 1 );
        }else{
            this._forceFinish = true;
            this.commonCallback();
        }
    }
}

//usage

var funMngr = new TestFun(finalFun, 60 * 1000);
funMngr.RegisterFun ( fun1 );
funMngr.RegisterFun ( fun2 );
funMngr.RegisterFun ( fun3 );
funMngr.Start();

function finalFun(){
    alert("all functions executed" );
}

答案 2 :(得分:0)

我已在评论中要求澄清,但我继续开始起草解决方案。这就是我想出的,希望这就是你的意思:

var AsyncBatch = function() {
    this.runnables = new Set();
};

AsyncBatch.prototype = {
    runnables: null,
    timeoutId: 0,

    add: function(runnable) {
        this.runnables.add(runnable);
    },

    start: function() {
        this.timeoutId = window.setTimeout(this.timeout.bind(this), 3000);

        let promises = [];
        for (let runnable of this.runnables) {
            promises.add(new Promise(resolve => {
                runnable(resolve);
            }));
        }
        Promise.all(promises).then(() => this.allDone());
    },

    allDone: function() {
        if (this.timeoutId == 0) return;
        window.clearTimeout(this.timeoutId);
        this.finish();
    },

    timeout: function() {
        this.timeoutId = 0;
        this.finish();
    },

    finish: function() {
        // Do something here when all registered callbacks are finished OR the batch timed out
    },

};

以下是您将如何使用它:

  1. 创建AsyncBatch
  2. 的实例
  3. 根据需要多次调用.add(),传递函数。这个函数应该需要一个参数,这是它在完成工作时应该调用的回调。
  4. .start()实例上调用AsyncBatch。它将异步执行所有可运行的操作,并启动计时器。
  5. 如果runnables在计时器用完之前全部完成,.allDone将取消计时器并执行.finish()
  6. 如果计时器在runnables之前用完,它会执行.finish(),并将timerId设置为0,这样当runnables全部完成时,.finish()不会再次被调用