How to call the same JavaScript function repeatedly while waiting for the function to run its course before invoking it again, using method chaining?

后端 未结 3 999
暗喜
暗喜 2020-11-30 14:24

Using method chaining, I am looking to fire a function repeatedly but only after the function has completed. Almost like don\'t execute until the function has fully run its

相关标签:
3条回答
  • 2020-11-30 14:56

    You are looking for Promises, though not supported across the board yet, you can use babel or traceur (or even jQuery's deferred) to use them now:

    var myfunc = {
      copy: function(message) {
        return new Promise(function(resolve, reject) {
          setTimeout(function() {
            resolve(message);
          }, 1000);
        });
      }
    }
    
    // sequential processing
    myfunc.copy('hello').then(function(message1) {
      console.log(message1);
      myfunc.copy('world').then(function(message2) {
        console.log(message2);
      });
    });
    
    // batch processing
    Promise.all([myfunc.copy('hello'), myfunc.copy('world')]).then(function(values) {
      console.log(values.join(' '));
    });
    

    Reference: Promise, Promise.all, Promise.then

    0 讨论(0)
  • 2020-11-30 14:57

    A working model with variable timeouts:

    var myfunc = {
        // the queue for commands waiting for execution
        queue: [],
    
        // (public) combined method for waiting 1000 ms and the displaying the message
        copy: function (message, wait) {
            // have a look for queue length
            var started = myfunc.queue.length;
            // push wait method with value if set or 1000 ms to queue
            myfunc.queue.push(myfunc.wait(wait || 1000));
            // push write message to queue
            myfunc.queue.push(myfunc.write(message));
            // if queue was empty, continuing command call has not started, get next commmand
            started || myfunc.next();
            // return whole object for chaining
            return this;
        },
    
        // set a timeout for the next next call
        wait: function (m) {
            return function () {
                setTimeout(myfunc.next, m);
            };
        },
    
        // do some action, here write message and call next
        write: function (message) {
            return function () {
                // present the message
                console.log(message);
                // call next command in queue
                myfunc.next();
            }
        },
    
        // the fabulous next method. calls the next command and delete it form the queue
        next: function () {
            // test if queue has a command to call, then shift the queue and call the function
            myfunc.queue.length && myfunc.queue.shift()();
        },
    };
    myfunc.copy('to').copy('be').copy('or', 2000).copy('not').copy('to').copy('be');
    myfunc.copy('that', 3000).copy('is').copy('the', 2000).copy('question');
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    Is there no way to store passed message(s) into an array to fire again after completion. So if it is fired again, it stores the new message in an array. Once initial completion, checks array to see if there are more values, then re-fires function using the next value in said array? I apologize if that sounds confusing.

    Maybe this is a solution for you:

    var myfunc = {
        queue: [],
        index: -1,
    
        copy: function (message, wait) {
            var started = myfunc.queue.length;
            myfunc.queue.push(myfunc.wait(wait || 1000));
            myfunc.queue.push(myfunc.write(message));
            started || myfunc.next();
            return this;
        },
    
        wait: function (m) {
            return function () {
                setTimeout(myfunc.next, m);
            };
        },
    
        write: function (message) {
            return function () {
                console.log(message);
                myfunc.next();
            }
        },
    
        next: function () {
            myfunc.index++;
            myfunc.index %= myfunc.queue.length;
            myfunc.queue[myfunc.index]();
        },
    };
    
    function go(i) {
        [
            function () { myfunc.copy('to').copy('be'); },
            function () { myfunc.copy('  or', 2000).copy('  not').copy('  to').copy('  be'); },
            function () { myfunc.copy('    that', 3000).copy('    is').copy('    the', 2000).copy('    question'); }
        ][i]();
    }
    
    go(0);
    setTimeout(go, 5000, 1);
    setTimeout(go, 20000, 2);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    0 讨论(0)
  • 2020-11-30 15:15

    If you don't want to use jQuery you can also have it as a pure JS solution.

    var myfunc = {
       timer: null,
       stack: [],
       copy: function(val) {
           if(this.timer == null) {
             console.log(val);
             target.innerHTML += val+"<br />";
             this.timer = setTimeout(function(){myfunc.onComplete();},1000);
           }
           else
             this.stack.push(val);
         
           return this;
       },
       onComplete: function() {
          var val = this.stack.shift();
          console.log(val);
          target.innerHTML += val+"<br />";
          if(this.stack.length) {
            this.timer = setTimeout(function(){myfunc.onComplete();}, 1000);
          }
          else this.timer = null;
       }
    };
    
    var target = document.getElementById('target');
    var trigger = document.getElementById('trigger');
    
    trigger.onclick = function(){
      myfunc.copy("hello").copy("world");
    }
    <button id="trigger">Start</button>
    <div id="target"></div>

    0 讨论(0)
提交回复
热议问题