如何使用方法链重复调用相同的 JavaScript 函数,等待函数完成其过程后再次调用它?

4

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

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个回答

10
一个具有可变超时时间的工作模型:

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


可以使用答案中的想法来回答另一个问题吗? - Morteza Tourani
@mortezaT,对我来说没问题。 - Nina Scholz

4
您正在寻找Promise(承诺)功能,尽管它们尚未得到全面支持,但您现在可以使用babel或traceur(甚至是jQuery的deferred)来使用它们:

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。没有办法把传递的消息存储到数组中,在完成后再次触发吗?因此,如果再次触发,则将新消息存储在数组中。一旦初始完成,检查数组以查看是否有更多值,然后使用该数组中的下一个值重新启动函数。如果这听起来令人困惑,请原谅。 - user3612986
在我看来,这是最清晰的答案。我认为发帖者正在要求一种不可能的同步和异步处理混合。 - user1636522

1
如果您不想使用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>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接