Enabling the chain method using ".delay"

I would like to know how to implement this method style:

var foo = function(){};

foo.prototype = {
 say : function(s){
        alert(s);
        return this;
       },
 delay : function(ms){
          var _this = this;
          setTimeout(function(){
           return _this;
          }, ms);
         return this; // If I omit this, there will be an error.
         }
}

var bar = new foo();
bar.delay(2000).say('hello'); // this will immediately alert 'hello'.

I want to use like this:

bar.delay(2000).say('hello'); // in 2 sec. say 'hello'.

not this way:

bar.delay(2000, function()...); // it not a chained method

Is it possible?

+3
source share
2 answers

Yes, it is possible, but you cannot do it simply returning from the function delay()after ms- the setTimeout calls are asynchronous and therefore return immediately. To achieve this effect, you must implement your own queuing system. Some code:

var queue = new Queue();

function delay(ms) {
    queue.enqueue("delay");
    setTimeout(function() {
        popQueue(true);
    }, ms);

    return this;
}

function say(s) {
    queue.enqueue(function() {
        alert(s);
    });
    popQueue();

    return this;
}

function popQueue(removeDelay) {
    if (removeDelay) {
        if (queue.peek() == "delay") queue.dequeue();
    }
    while (!queue.isEmpty() && queue.peek() != "delay") {
        (queue.dequeue())();
    }
}

, , , "", , . delay() "", , . .

, , . , - Queue implementation, , SelfExecutingQueue ( , ) , , popQueue() ..

+3

, ! .

var foo = function(){};

foo.prototype = {
 say : function(s){
  Queue.enqueue(function(){
   alert(s);
  });
  Queue.flush();
  return this;
 },
 delay : function(ms){
  Queue.enqueue('delay:' + ms);
  return this;
 }
}

Queue = {
 entries : [],
 inprocess : null,
 enqueue : function(entry){
  Queue.entries.push(entry);
 },
 flush : function(){
  if(Queue.inprocess) return;
  while (Queue.entries.length){
   var entry = Queue.entries.shift();
   if(entry.toString().indexOf('delay:') !== -1){
    var ms = Number(entry.split(':')[1]);
    Queue.inprocess = setTimeout(function(){
     Queue.inprocess = null;
     Queue.flush();
    }, ms);
    return;
   }
   entry();
  }
 }
}

Queue . :

var bar = new foo();
bar.delay(2000).say('Hello, ').delay(3000).say('world!');

!

0

Source: https://habr.com/ru/post/1758394/


All Articles