简体   繁体   English

在JavaScript中具有常见回调的类

[英]Class with common callback in javascript

i want to build a javascript class to register several different functions to execute a single common callback, all registered functions should execute asynchronously and then once all of them are finished, it should execute the defined callback function . 我想构建一个javascript类来注册几个不同的函数以执行一个通用回调,所有注册的函数应异步执行,然后在所有这些函数完成后,便应执行定义的回调函数

We should also be able to define a maximum time before the callback function executes. 我们还应该能够定义回调函数执行之前的最长时间 For example if we define that as 3000 and it takes more than 3000 ms for all registered functions to return, it should proceed to execute callback function even though the ajax functions have not finished retuning. 例如,如果我们将其定义为3000,并且所有注册的函数都需要3000毫秒以上的时间才能返回,则即使ajax函数尚未完成重新调整,它也应继续执行回调函数。

To be clear, this code needs to be flexible, standalone and reusable 需要明确的是,此代码必须灵活,独立且可重用

To assume that any function that we register will implement a call to a function that we define at some point within it mark its completion. 假定我们注册的任何函数都将实现对我们在其中定义的某个点的函数的调用,以表示该函数已完成。 for eg. 例如 at the end of my function i'll enter myClass.markDone() to let the class know the function has completed executing 在函数的末尾,我将输入myClass.markDone() ,让类知道该函数已完成执行

Is it possible using javascript or with angular.js and without jquery? 是否可以使用javascript或使用angular.js而不使用jquery?

To achieve this take a look at these angular built in modules: 为此,请看一下这些内置的angular模块:

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

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

Here is an example implementation on plunkr: 这是在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 http://plnkr.co/edit/hNo9kJmKIR4hEoNk9pP2?p=preview

iam not sure this will work, am not tested. 我不确定这是否有效,未经测试。 this may give you some idea. 这可能会给您一些想法。

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" );
}

I asked for clarification in a comment already, but I went ahead and started drafting a solution. 我已经在评论中要求澄清,但我继续进行并开始草拟解决方案。 Here's what I came up with, hope this is what you meant: 这是我想出的,希望这就是您的意思:

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
    },

};

Here's how you would use this: 这是您的使用方式:

  1. Create an instance of AsyncBatch . 创建一个AsyncBatch的实例。
  2. Call .add() as many times as you want, passing a function. 根据需要多次调用.add() ,并传递一个函数。 This functions should expect a single parameter, which is the callback it should invoke when its job is done. 此函数应包含一个参数,即完成工作后应调用的回调。
  3. Call .start() on the AsyncBatch instance. AsyncBatch实例上调用AsyncBatch .start() It will execute all runnables asynchronously, as well as start a timer. 它将异步执行所有可运行对象,并启动计时器。
  4. If the runnables all finish before the timer runs out, .allDone will cancel the timer and execute .finish() . 如果可运行对象在计时器用尽之前全部完成,则.allDone将取消计时器并执行.finish()
  5. If the timer runs out before the runnables, it executes .finish() , and sets the timerId to 0 so that .finish() won't be called again when the runnables all finish. 如果计时器在可运行对象之前用完,它将执行.finish() ,并将timerId设置为0,以便当所有可运行对象完成时不会再次调用.finish()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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