Question

(This question is not really restricted to the language so please feel free to submit solution in other languages too.)

I was just wondering if it would be possible to write something like this in JavaScript:

// Wait 3 seconds and then say our message in an alert box
wait(3).then(function(){alert("Hello World!");});

Where the traditional way would be to write

// Wait 3 seconds and then say our message in an alert box
setTimeout(function(){alert("Hello World!");}, 3000);

Sorry if this is a noob question :p

Was it helpful?

Solution

You can write it easily:

function wait(delay) {
  return {
    then: function (callback) {
      setTimeout(callback, delay*1000);
    }
  };
}

wait(3).then(function(){alert("Hello World!");});

If you want to go in-deep, I recommend you to read about currying and partial function application, those topics are really interesting.

OTHER TIPS

Yet another version, without closure:

function wait(seconds) {
    if(this instanceof wait)
        this.delay = seconds;
    else return new wait(seconds);
}

wait.prototype.then = function(callback) {
    setTimeout(callback, this.delay * 1000);
};

With some more code, you can even call the functions repeatedly:

function wait(seconds) {
    if(this instanceof wait)
        this.delay = seconds;
    else return new wait(seconds);
}

wait.prototype.then = function(callback) {
    setTimeout(callback, this.delay * 1000);
    return this;
};

wait.prototype.wait = function(seconds) {
    this.delay += seconds;
    return this;
};

var start = new Date;
function alertTimeDiff() {
    alert((new Date - start)/1000);
}

wait(1).then(alertTimeDiff).wait(3).then(alertTimeDiff);

Chaining is rather used to execute multiple methods on one object. So you would rather consider the function as the object and set the timeout there:

Function.prototype.callAfter = function(delay) {
    setTimeout(this, delay*1000);
};

(function(){alert("Hello World!");}).callAfter(3);

If you do OO Javascript, then yes, you can do method chaining.

Some of the popular JavaScript frameworks do this. jQuery does this by returning the jQuery object for functions that usually wouldn't return a value.

I just wrote a little helper to create APIs like this in a somewhat consistent way, maybe you like it.

// > npm i mu-ffsm # install node dependency
var mkChained = require('mu-ffsm');

The idea is that you construct a fluent builder with some initial state of type S by calling an entry function. Then each chained call transitions the state to a new state.

The value you get from chaining a bunch of calls can be executed as a function, which calls exit to construct a value from that state and any options you pass in.

  • entry : * ⟶ S
  • transition : (S ⟶ *) ⟶ S
  • exit : S ⟶ (* ⟶ *)

For example

var API = mkChained({
  0:    function(opt)    {return ;/* create initial state */},
  then: function(s, opt) {return s; /* new state */},
  whut: function(s, opt) {return s; /* new state */},
  1:    function(s, opt) {return ;/* compute final value */}
});

So 0, 1 are entry, exit functions. All other functions transition an internal state. All functions can take arguments, eg. opt

We create an instance of our newly crafted API,

var call = API() // entry
   .whut()       // transition
   .then()       // transition
   .whut();      // transition

And call it

var result0 = call() // exit
  , result1 = call() // exit

Have a look at the (small) source to see how this is implemented.

ps. Used this answer to update docs :D

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top