使用方法链,如何在等待函数运行完毕后再再次调用它时重复调用相同的 JavaScript 函数?

IT技术 javascript method-chaining
2021-03-01 08:43:07

使用方法链,我希望重复触发一个函数,但只有在该函数完成之后。几乎就像在函数完全运行之前不要执行一样。预期结果示例:

var myfunc = {
    copy: function(message){
        window.setTimeout(function(){
           console.log(message);
        },1000);
        return this;
    }
};
myfunc.copy('hello').copy('world'); 
// wait a second then log:
// hello
// wait until first function completion (1000ms), wait a second then log:
// world

任何帮助表示赞赏!

3个回答

具有可变超时的工作模型:

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

有没有办法将传递的消息存储到数组中以在完成后再次触发。因此,如果它再次被触发,它会将新消息存储在一个数组中。初始完成后,检查数组以查看是否有更多值,然后使用所述数组中的下一个值重新触发函数?如果这听起来令人困惑,我深表歉意。

也许这对你来说是一个解决方案:

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

可以将答案想法用于另一个.
2021-04-22 08:43:07
@mortezaT,我没问题。
2021-05-15 08:43:07

您正在寻找 Promises,虽然尚未全面支持,但您现在可以使用 babel 或 traceur(甚至 jQuery 的延迟)来使用它们:

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(' '));
});

参考:PromisePromise.allPromise.then

谢谢 Rob M。有没有办法将传递的消息存储到数组中以在完成后再次触发。因此,如果它再次被触发,它会将新消息存储在一个数组中。初始完成后,检查数组以查看是否有更多值,然后使用所述数组中的下一个值重新触发函数?如果这听起来令人困惑,我深表歉意。
2021-04-27 08:43:07
在我看来,最清晰的答案是,我认为海报要求同步和异步处理的不可能混合。
2021-05-06 08:43:07

如果您不想使用 jQuery,您也可以将其作为纯 JS 解决方案使用。

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>